; Animals.asm
;
	.org	8050h		; Punto di caricamento di Mo51
;
        mov     sp,#70h
;
;       Inizializzazione
;
        MOV     IE,#0           ; nessun interrupt
        MOV     SCON,#52H       ;
        MOV     TMOD,#22H       ;
        MOV     TCON,#59H       ;
        MOV     TH1,#0FDH       ; 9600 baud
;
        sjmp     Start   	; Va subito a Start
;
;
.equ	CR, 13
.equ	LF, 10
;
.equ	InLen, 10		; Dimensione buffer di input
;
;	Area Subroutines
;
; -- PutChar
;       Stampa un caratere in ACC
;       Input:
;               ACC = carattere da stampare
;       Output:
;               Nessuno.
;       Modifica
;               Niente.
PutChar:
        jnb     ti,PutChar	; Attende carattere
        mov     sbuf,a		; Mette carattere in ACC
        clr     ti		; Azzera flag carattere ricevuto
        ret
;
; -- PutString
;	Stampa una stringa terminata da 0
;	Input:
;               DPTR = Indirizzo della stringa da stampare
;	Output:
;		Nessuno.
;	Modifica:
;               DPTR,A
;
PutString:
        clr     a		; 'indice' (sommato a DPTR)
        movc    a,@a+dptr	; leggo caratere corrente
	jz	EndPS		; ho leto lo 0 finale: esco
        acall   PutChar		; stampo il carattere (<> 0)
        inc     dptr		; passo al prossimo carattere
        sjmp    PutString	; loop
;
EndPS:	ret

;
; -- GetString
;	Legge una stringa da tatstiera fino a CR. Pone il risultato
;       nella striga puntata da R0 per un massimo indicato in R1
;	Input:
;               R0 = Indirizzo del buffer
;               R1 = Dimensione del buffer
;	Output:
;               R1 = caratteri restanti
;	Modifica:
;               R1,A
;
GetString:
        mov     a,r0
        push    acc     	; per poi
LPGS:   jnb     ri,LPGS		; Attende carattere
        mov     a,sbuf 		; legge il carattere
        clr     ri      	; pulisce il flag
        lcall	PutChar 	; Echo
        cjne    a,#CR,NoCr 	; Controla se CR
        sjmp    EndGs   	; fine ...
NoCr:
        mov     @r0,a   	; mette il carattere nel buffer
        inc     r0		; incrementa puntatore al buffer
        djnz    r1,LPGS 	; continua fino a fine buffer
;
EndGs:
        clr     a
        mov     @r0,a  		; mette il terminatore (0)
        mov     dptr,#CrLf      ; Stringa con CR ed LF
        acall   PutString       ; Stampa CR,LF (echo)
        pop     acc     	; Ripristina R0
        mov     r0,a
	ret
;
;
; -- Question
;	Presenta una domanda, legge la risposta e pone in DPTR
;	il puntatore alla prossima domanda
;	Input:
;               DPTR = puntatore alla domanda
;	Output:
;               DPTR = puntatore prossima domanda (se 0 -> termine)
;	Modifica:
;               DPTR,A,r4,r5,r6,r7
;
Question:
	; R5-R4 -> puntatore a prossima domanda se risposta == 'Si'
        clr     a
        movc    a,@a+dptr  ; parte alta puntatore 'Si'
        mov     r5,a
        inc     dptr
        clr     a
        movc    a,@a+dptr  ; parte bassa puntatore 'Si'
        mov     r4,a
        inc     dptr
	; R7-R6 -> puntatore a prossima domanda se risposta == 'No'
        clr     a
        movc    a,@a+dptr  ; parte alta puntatore 'No'
        mov     r7,a
        inc     dptr
        clr     a
        movc    a,@a+dptr  ; parte bassa puntatore 'No'
        mov     r6,a
        inc     dptr
	; Adesso DPTR punta al testo della domanda
	acall	PutString ; Stampa la domanda
        mov     a,r6
        orl     a,r7    ; r6,r7 = 0? (No) -> nessun'altra domanda (era una risposta)
	jz	No	; copia R6-R7 in DPTR ed esce
;
Ripeti:
;
        mov     dptr,#Quest	; "?\n(Si/No) "
	acall	PutString	; stampa il punto dio domanda dopo la domanda
        mov     r0,#InBuff
        mov     r1,#InLen
	acall	GetString	; Legge la risposta
        mov     a,@r0  		; legge la prima lettera
        cjne    a,#'N',CmpNo	; Risposta <> 'N...' (No)
        sjmp    No		; Risposta 'no'
CmpNo:
        cjne    a,#'n',CmpS	; Risposta <> 'n...' (no)
        sjmp    No		; Risposta 'no'
CmpS:
        cjne    a,#'S',CmpSi	; Risposta <> 'S...' (Si)
        sjmp    Si		; Risposta 'si'
CmpSi:
        cjne    a,#'s',Ripeti	; Risposta <> 's...' -> non valida
;
Si:     mov     dpl,r4		; Copia puntatore R5-R4 (Si) in DPTR (corrente)
        mov     dph,r5
        sjmp    QFine
;
;
No:     mov     dpl,r6		; Copia puntatore R7-R6 (No) in DPTR (corrente)
        mov     dph,r7
QFine:
	ret

;
; Loop principale (main)
;
Start:
        mov     dptr,#benvenuto	; Messaggio di apertura
	acall	PutString
        mov     dptr,#FirstQ	; Puntatore alla radice dell'albero
GameLp:	acall	Question	; Presenta la domanda e legge la risposta
;
        mov     a,dph		; Controlla il dato tornato (DPTR)
        orl     a,dpl
	jnz	GameLp		; Se DPTR <> 0, ho ancora domande, continuo
        sjmp     Start		; altrimenti ritorno all'inizio
;
.equ	InBuff, 8       	; Dopo i registri in ram DATA
;
benvenuto:
        .db      CR,LF,CR,LF,"Programma ANIMALI",CR,LF,CR,LF
        .db      "Programma che indovina l'animale",CR,LF
CrLf:   .db      CR,LF,0
;
; Database domande
;
Quest:  .db      "?",CR,LF,"(Si,No)? ",0
;
FirstQ:	.dw	Uccello,Mammifero
        .db      "L'animale depone le uova",0

Uccello: .dw	Volatile,Terrestre	
        .db      "L'animale vola",0

Volatile: .dw	0,0	; Nessun puntatore -> risposta
        .db      "L'animale e' un'uccello",0

Terrestre: .dw	Struzzo,Pinguino
        .db      "L'animale corre veloce",0

Struzzo: .dw	0,0
        .db      "L'animale e' uno Struzzo",0

Pinguino: .dw	0,0
        .db      "L'animale e' un pinguino",0

Mammifero: .dw	Pipistrello,Mucca
        .db      "L'animale vola",0

Pipistrello: .dw 0,0
        .db      "L'animale e' un pipistrello",0

Mucca:	.dw	0,0
        .db      "L'animale e' una Mucca",0
	.end
;
