;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Exercice d'assembleur dans le cours de systeme d'exploitation 2 de Louis 
; Marchand.
; PacMan en assembleur NES
; Création: Marie-Michèle Fauteux
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;; Entète de la rom ;;;;;;;;;;;
	.inesprg 1 ; 1 banque de 16KB (2 banque de 8KB) pour le programme
	.ineschr 1 ; 1 banque de 8KB pour les image (2 tables de motifs)
	.inesmap 0 ; mapper 0 = NROM, Banque par défaut
	.inesmir 1 ; Mirroir vertical de l'image de fond

	.code
;==============================================================================
;BANK 0
;==============================================================================	
	.bank 0   ; Banque 0 (8KB de $C000 à $DFFF
	.org $C000  ; goto location $C000.

;------------------------------------------------------------------------------
; init
;------------------------------------------------------------------------------

Start:
	SEI         ; Arreter les interruption, Met le bit I du registre P (etat du processeur) a 1
	CLD         ; Arrete le mode decimal. Met le bit D du registre P à 0
	LDX #$40
	STX $4017  ;  Met $40 dans le registre de controle de l'APU pour arreter les interruptions de l'APU
	LDX #$FF
	TXS         ; Initialise la pile. Place X ($FF$ comme octet moins significatif de l'adresse de la pile). La pile est toujours entre $0100 et $01FF.
	INX         ; Lorsqu'on incremente X qui contient $FF, C tombe à 0
	STX $2000  ;  Arrete les interruption NMI (Bit 7 du registre Contrôle PPU)
	STX $2001  ;  N'affiche rien (Voir bits 3 à 7 du registre Masque PPU)
	STX $4010  ;  Arrete les interruption logiciel

	JSR vblankwait	; Place l'adresse en cour sur la pile et branche vers la routine "vblankwait"

clrmem:
	LDA #$00
	STA $0000,  x		; Place tous les octets à 0 (", x" correspond a l'adressage indexe avec le registre x)
	STA $0100,  x
	STA $0300,  x
	STA $0400,  x
	STA $0500,  x
	STA $0600,  x
	STA $0700, x
	LDA #$FE
	STA $0200, x		; Placer tous les sprite en dehors de l'écran (Je place mes sprites dans les adresses $0200 à $02FF)
	INX					; Prochaine itération
	BNE clrmem		; Branche si non zero (lorsque x a fait le tour des valeurs de $00 à $FF)

	JSR vblankwait	; Place l'adresse en cour sur la pile et branche vers la routine "vblankwait"

;;;;  Initialise le PPU  ;;;;

LoadPalettes:
 	LDA $2002    		; Lire le registre d'etat du PPU ou annuler le latch de $2006 (s'il y a lieu)
	LDA #$3F	
	STA $2006    		; Place les 8 bits les plus significatifs de l'adresse $3F00 dans $2006
	LDA #$00
	STA $2006    		; Place les 8 bits les moins significatifs de l'adresse $3F00 dans $2006
	LDX #$00
LoadPalettesLoop:
	LDA palettes, x		; Charge les donnees de la palette (", x" correspond a l'adressage indexe avec le registre x)
	STA $2007		; Place les informations du PPU (l'adresse d'écriture de $2007 incrémente automatiquement de 1 octet après chaque ecriture)
	INX			; Prochain index a aller chercher dans la palette en memoire rom (etiquette palette+x)
	CPX #32            
	BNE LoadPalettesLoop 	; La palette est completement copiees si x est à 32=16x2


; Initialisation des sprites
        LDX #0
LoadSpritesData:
        LDA SpriteData, x       ; SpriteData est en ROM (lecture seule). Pour pouvoir modifier
        STA $0000, x            ; ces sprites, nous transf�rons les donn�es des sprites en RAM
        INX
        CPX #20         ; il y a 5 sprites de 4 octets (donc 64 octets) � transf�rer en RAM
        BNE LoadSpritesData



LoadName:
	LDA #$20	; Nous utiliserons la table de nom 0 (Adr $2000)
	STA $2006
	LDA #$00
	STA $2006
	LDX #0	; x sera notre index de largeur
	LDY #0	; y sera notre index de hauteur
LoadNameLoop:
	STA $2007	; Mettre la tuille no 0 dans la table
	INX
	CPX #32
	BNE LoadNameLoop	; Lorsque x=32, on a une ligne pleine
	LDX #0
	INY
	CPY #30
	BNE LoadNameLoop	; lorsque y=30, on a terminer (32x30 tuiles)

	LDX #0
	LDA #0	; Changer cette valeur pour changer la sous-palette de couleur à utiliser (2 bits par 2x2 tuiles)
LoadAttribute:
	STA $2007
	INX
	CPX #64
	BNE LoadAttribute ; Il y a 64 attribut
	
	JSR vblankwait	; Place l'adresse en cour sur la pile et branche vers la routine "vblankwait"

	JSR activePPU
;--------------------------------------------------------------------------------------------
; LOOP
;--------------------------------------------------------------------------------------------

Forever:
	LDX #$00
	LDY #$00
	LDA #$01	; Écrire $01 et $00 dans $4016 place l'état du controlleur 1 dans $4016 et du controlleur 2 dans $4017
	STA $4016
	LDA #$00
	STA $4016
ReadButtonLoop:			; Valide chaque bouton
	LDA $4016, y		; Lit l'état du controlleur (si Y est à 0, lit $4016 et si Y est à 1, lit $4017)
	AND #%00000001		; Le bouton est appuyé si le AND ne retourne pas 0.
	BEQ NotReadButton
	ORA $0202, x		; Bouton pressé; Met les bits d'attribut du sprite à 1
	STA $0202, x
	JMP FinReadButtonCTRL
NotReadButton:			; Bouton non pressé
	LDA #%11111100
	AND $0202, x		; Met les bits d'attribut du sprite à 0
	STA $0202, x
FinReadButtonCTRL:
	INX			; Prochain sprite (4 octets par sprite) et prochain bouton
	INX
	INX
	INX
	CPX #32			; Controller 1 terminé. 8 boutons lu (8*4=32)
	BNE FinReadButton1
	INY
	JMP ReadButtonLoop
FinReadButton1
	CPX #64			; Controller 2 terminé. . 16 boutons lu (16*4=64)
	BNE ReadButtonLoop
	JMP Forever     ;Boucle sans fin, le processus se fera lors d'interruption NMI

;-------------------------------------------------------------------------------------
; routine
;-------------------------------------------------------------------------------------

NMI:
	RTI             ; retourne de l'interruption
  
vblankwait:			; Routine qui attend que l'écran ait terminé de s'afficher (pour éviter les problèmes visuels)
	BIT $2002		; Bit place les Code de condition N, V, Z.
	BPL vblankwait	; Si le bit 7 est allumé, on a un vblank (BPL = N flag clear, le bit de negatif = bit 7)
	RTS	
	
	
activePPU:
	LDA #%10010100		; Active les interruption NMI, table de motif: sprite = 0 et image de fond = 1
	STA $2000
	LDA #%11111110		; Active l'image de fond, mais pas les sprites
	STA $2001
	LDA #$00		;Ne pas faire de defilement d'image
	STA $2005
	STA $2005
	RTS
	
;====================================================================
; BANK 1
;====================================================================

;;;;;;Espace mémoire pour stocker les palettes;;;;;;;;;;;;;;;;;;;;;;;
	bank 1
	.org $E000 
	
	palettes:
        .db $01, $37, $35, $31, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; palette du fond d'écran
	.db $30, $30, $24, $31, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00; palettes des sprites
	
	SpriteData:
	.db $40, 0, %00000000, $10	; 
	.db $40, 1, %00000000, $2F	; 
	.db $40, 2, %00000000, $3E	; 
	.db $40, 3, %00000000, $4D	; 
	.db $40, 4, %00000000, $5C	; 
	
	.org $FFFA	; vecteur d'interruption commence à $FFFA

	.dw NMI		; Interruption NMI (vblank). Adresse $FFFA
	.dw Start	; Interruption Reset (demarrage). Adresse $FFFC
	.dw 0		; Interruption logiciel (instruction BRK). Adresse $FFFE

	
;====================================================================
; BANK 2
;====================================================================

	.bank 2        ; change to bank 2 (banque de 16kb du ROM inclue dans la PPU au démarrage)
	.org $0000

	; Ici, on place les tuile pour le sprite
	; SPRITE PACMAN

	PacmanO:               ;  pacman with mouth shut
	.db %00111100  ;    ####
	.db %01111110  ;   ######
	.db %11111111  ;  ########
	.db %11111111  ;  ########
	.db %11111111  ;  ########
	.db %11111111  ;  ########
	.db %01111110  ;   ######
	.db %00111100  ;    ####

	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;

PacmanR:               ;  pacman looking right ready for a deapthroat
	.db %00111100  ;    ####
	.db %01111110  ;   ######
	.db %11111110  ;  #######
	.db %11111100  ;  ######
	.db %11110000  ;  ####
	.db %11111100  ;  ######
	.db %01111110  ;   ######
	.db %00111100  ;    ####

	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;

PacmanU:               ;  pacman looking right ready to be shited in mouth
	.db %00000000  ;    
	.db %01100010  ;   ##   #
	.db %11110111  ;  #### ###
	.db %11110111  ;  #### ###
	.db %11111111  ;  ########
	.db %11111111  ;  #######
	.db %01111110  ;   #####
	.db %00111100  ;    ###

	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;

PacmanD:               ;  pacman looking down, eating shit
	.db %00111100  ;    ####
	.db %01111110  ;   ######
	.db %11111111  ;  ########
	.db %11111111  ;  ########
	.db %11101111  ;  ### ####
	.db %11101111  ;  ### ####
	.db %01000110  ;   #   ##
	.db %00000000  ;

	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;

PacmanL:               ;  pacman looking backward
	.db %00111100  ;    ####
	.db %01111110  ;   ######
	.db %11111110  ;   #######
	.db %11111100  ;    ######
	.db %11110000  ;      ####
	.db %11111100  ;    ######
	.db %01111110  ;   ######
	.db %00111100  ;    ####
	
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;

Ghosts:
	.db %00111100 	
	.db %01111110  
	.db %11001001   
	.db %11011011  
	.db %11111111
	.db %11111111
	.db %11111111
	.db %10100101 

	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;
	.db %00000000  ;

	.org $1000	; Motif de background
	
BackgroundMotif10:	; Tuile 0
	.db %10000001, %10000001
	.db %01000010, %01000010
	.db %00100100, %00100100
	.db %00011000, %00000000
	.db %00011000, %00000000
	.db %00100100, %00100100
	.db %01000010, %01000010
	.db %10000001, %10000001

BackgroundMotif1:	; Tuile 1
	.db %10000001		; Bit le moins significatif de la premiere ligne de la tile
	.db %01000010		; Bit le moins significatif de la deuxieme ligne de la tile
	.db %00000000		; Bit le moins significatif de la troisieme ligne de la tile
	.db %00000000		; Bit le moins significatif de la quatrieme ligne de la tile
	.db %00000000		; Bit le moins significatif de la cinquieme ligne de la tile
	.db %00000000		; Bit le moins significatif de la cixieme ligne de la tile
	.db %01000010		; Bit le moins significatif de la septieme ligne de la tile
	.db %10000001		; Bit le moins significatif de la huitieme ligne de la tile

	.db %10000000		; 2e Bit le moins significatif de la premiere ligne de la tile
	.db %00000000		; 2e Bit le moins significatif de la deuxieme ligne de la tile
	.db %00010000		; 2e Bit le moins significatif de la troisieme ligne de la tile
	.db %00000000		; 2e Bit le moins significatif de la quatrieme ligne de la tile
	.db %00000000		; 2e Bit le moins significatif de la cinquieme ligne de la tile
	.db %00000000		; 2e Bit le moins significatif de la cixieme ligne de la tile
	.db %00001000		; 2e Bit le moins significatif de la septieme ligne de la tile
	.db %00000000		; 2e Bit le moins significatif de la huitieme ligne de la tile


	




