SN76489 simulator/translator/emulator on AY-3-8910

By hbarcellos

Hero (559)

hbarcellos's picture

02-06-2014, 02:31

Ok, I thought I would have way more time to improve this, but...

*BTW* this is not the one used on the conversions. This one is a preliminary/not optimized at all/probably with a lot of errors/draft that I did to test some noise emulation. This is the only converted game using it (never released)

Maybe someone can spot/improve it while I'm flooded at my 9to17, 17to23, 5to9 jobs...

;
;	COLECO SOUND EMULATION reloaded - BY MUFFIE 2014
;

LATCH:			DB 00		; tenho que gravar a porra do ultimo latch...
FREQLOW:		DB 00		; PARTE BAIXA DO SOM
FLAGNOISE:		DB 00
VOLUMEC:		DB 00

;;Muffie's note to self
;; AY-CHIP
;;	Channel A, tone period: xxxxyyyyzzzz = xxxx in R1 and yyyyzzzz in R0
;;


; SN REGISTERS DUMP
;LATCH:			DB %00000000
VOL0:			DB %00000000			; xxxx0000
VOL1:			DB %00000000			; xxxx0000
VOL2:			DB %00000000			; xxxx0000
;VOLN:			DB %00000000			; xxxx0000
TON0L:			DB %00000000			; 00000000	;R0
TON0U:			DB %00000000			; xxxxxx00	;R1
TON1L:			DB %00000000			; 00000000	;R2
TON1U:			DB %00000000			; xxxxxx00	;R3
TON2L:			DB %00000000			; 00000000	;R4
TON2U:			DB %00000000			; xxxxxx00	;R5
TONN:			DB %00000000			; xxxxx000	

REG7:		DB $00

INIT_SOUND:
	PUSH AF
	LD	A,7
	OUT	($A0),A
	LD A,%10111000	; sem ruido
	OUT ($A1),A
	LD (REG7),A

	LD A,8
	OUT	($A0),A	; Selecionei registrador 8, volume do canal A , carregado no a  do PSG
	LD A,%00000000 ;  Modo Fixo, volume ZERO
	OUT ($A1),A	; gravei

	LD A,9
	OUT	($A0),A	; Selecionei registrador 9, volume do canal B , carregado no a  do PSG
	LD A,%00000000 ;  Modo Fixo, volume ZERO
	OUT ($A1),A	; gravei

	LD A,10
	OUT	($A0),A	; Selecionei registrador 10, volume do canal c , carregado no a  do PSG
	LD A,%00000000 ;  Modo Fixo, volume ZERO
	OUT ($A1),A	; gravei
	
	; agora vamos apagar os tons
	LD A,0
	OUT	($A0),A	; Selecionei registrador 0, tom do canal A
	LD A,%00000000 ; 
	OUT ($A1),A	; gravei
	LD A,1
	OUT	($A0),A	; Selecionei registrador 1, tom do canal A
	LD A,%00000000 ; 
	LD A,2
	OUT	($A0),A	; Selecionei registrador 2, tom do canal A
	LD A,%00000000 ; 
	OUT ($A1),A	; gravei
	LD A,3
	OUT	($A0),A	; Selecionei registrador 3, tom do canal A
	LD A,%00000000 ; 
	LD A,4
	OUT	($A0),A	; Selecionei registrador 4, tom do canal A
	LD A,%00000000 ; 
	OUT ($A1),A	; gravei
	LD A,5
	OUT	($A0),A	; Selecionei registrador 5, tom do canal A
	LD A,%00000000 ; 

	POP AF
	RET
; ---------QDEMU - By Muffie 201477--------------------------------------------------------------
TOCA_SOM_COLECO:
	PUSH AF
	PUSH BC
	PUSH HL
	PUSH DE
	
	;LD A,($e050)	;; TESTE PARA COMUNICAR COM BASIC
	
	LD B,A			; 
	BIT 7,A
	JP Z,TS_DADOS

TS_REGISTRO:					;;LATCH/DATA BYTE	
	LD (LATCH),A
	AND %00010000				; SE DER ZERO … FREQUENCIA
	JR Z,TS_FREQUENCIA
TS_VOLUME:						; SEN√O … VOLUME...
	LD A,B
	AND %01100000
	RRCA
	RRCA
	RRCA
	RRCA
	RRCA						; N⁄MEROS BONITINHOS: 0 = CANAL 0, 1 = CANAL 1, 2 = CANAL 2 E 3=CANAL RUIDO!
	LD C,A						; C TEM O CANAL
TS_VOLUME_JUMP_FROM_DATA:
	LD A,B						;; VOLTEI PRA PEGAR O VOLUME
	AND %00001111
	CPL
	AND %00001111				; VOLUME NO COLECO EH INVERTIDO
	LD B,A						; B AGORA TEM O VOLUME CERTINHO	
	LD A,C
	CP  %00000011				; SER¡ QUE ELE QUER O VOLUME DO RUIDO?
	JR Z,TS_VOLUME_RUIDO	
	LD A,8
	ADD A,C						; PARA PEGAR O REGISTRADOR CERTO PARA O VOLUME DE CADA CANAL
	OUT ($A0),A
	LD A,B	
	OUT ($A1),A					; PRONTO, VOLUME "SETADO"
	LD HL,VOL0					;; AGORA VOU SALVAR O VOLUME NA MEMORIA VOL0,VOL1,VOL2
	LD B,0
	ADD HL,BC					;
	LD (HL),A					; SALVEI O VOLUME TAMBEM

	JP TS_FIM
TS_VOLUME_RUIDO:
	LD A,B						; B j· tinha o volume em formato xxxx0000
	OR A						; S” FICA MUTE SE O VOLUME FOR ZERO. QQ COUSA DIFERENTE, LIGAR¡
	JR Z,OFFRUIDO
ONRUIDO:
	CALL LIGA_NOISE
	JR TS_FIM					;
OFFRUIDO:
	CALL DESLIGA_NOISE
	JR TS_FIM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FIM VOLUME (PARTE DO LATCH/DATA BYTE DO SN)
	
TS_FREQUENCIA:
	LD A,B						; O B AQUI AINDA TEM O LATCH FULL
	CALL GET_CHANNEL_FROM_A
	LD C,A						; C AGORA TEM O CANAL CERTINHO
	CP %00000011				; O CARA QUER O CANAL DE RUIDO?
	JR Z,TS_FREQ_RUIDO2		
	LD A,B
	LD B,$0
	RLC C						; MULTIPLICADO POR DOIS, MAS SEMPRE A PARTE BAIXA DOS CANAIS
	LD HL,TON0L					; INICIO DOS REGISTROS
	ADD HL,BC					; PARTE BAIXA DO CANAL CORRETO
	AND %00001111				; AGORA A TEM A FREQUENCIA
	LD (HL),A					; GRAVEI A PARTE BAIXA NO TOM DO CANAL CORRETO
	JP OUTPUT_CHANNEL
	
TS_FREQ_RUIDO2:					; PULA DIRETO DOS DADOS TB
	LD HL,TONN
	LD A,B
	AND %00000011				; O RUIDO DO COLECO SOH TEM 2 BITS
	LD B,%00001100
	CP %00000000				; RUIDO ZERO DO COLECO = N/512				
	JR Z,TS_FREQ_RUIDO2_FIM
	LD B,%00010000				; RUIDO 01 DO COLECO = N/1024
	CP %00000001
	JR Z,TS_FREQ_RUIDO2_FIM
	LD B,%00011111
	CP %00000010				; RUIDO 02 DO COLECO = N/2048
	JR Z,TS_FREQ_RUIDO2_FIM		; SENAO, TA CHUPINHANDO DO TONE 3

	LD A,(TON2L)
	RRA
	RRA
	RRA
	AND %00011111
	LD B,A
	
TS_FREQ_RUIDO2_FIM:
	LD A,B
	LD (HL),A
	JP OUTPUT_CHANNEL
	
TS_FIM:
	POP DE
	POP HL
	POP BC
	POP AF
	RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FIM DO (LATCH/DATA BYTE DO SN)
	
TS_DADOS:
	LD A,(LATCH)				; PEGUEI O ULTIMO QUE VEIO ANTES
	BIT 4,A						; 0 … TOM OU NOISE, 1 … VOLUME
	JR NZ,TS_DADOS_VOLUME			;
	CALL GET_CHANNEL_FROM_A
	CP %00000011				; O CARA QUER O CANAL DE RUIDO?
	JR Z,TS_FREQ_RUIDO2		
TS_DADOS_TOMS:
	LD C,A						; C AGORA TEM O CANAL CERTINHO
	LD D,B						; SALVEI O BYTE DE DADOS EM D
	LD B,$0
	LD HL,TON0L
	RLC C						; CADA CANAL OCUPA 2 BYTES, TEM QUE MULT2 PARA ACHAR A PARTE BAIXA CORRETA
	ADD HL,BC
	LD A,D
	AND %00001111
	RLCA
	RLCA
	RLCA
	RLCA
	LD E,A
	LD A,(HL)
	ADD A,E
	LD (HL),A					; GRAVEI OS 4 DA DIREITA DOS DADOS 
	INC HL						; AGORA VOU PARA A PARTE ALTA DO REGISTRO DE TOM
	LD A,D
	AND %00110000				; A PARTE DE BAIXO J¡ SALVEI
	RRCA
	RRCA
	RRCA
	RRCA
	LD (HL),A					; PRONTO, DEVO TER O TOM CORRETO
	JP	OUTPUT_CHANNEL			; EH FREQUENCIA
	
TS_DADOS_VOLUME:
	CALL GET_CHANNEL_FROM_A
	LD C,A						; TENHO QUE PREPARAR O C PARA O JUMP
	JP TS_VOLUME_JUMP_FROM_DATA	; EM B AINDA TENHO O ORIGINAL DE DADOS, VOLUME. NEM DEVE EXISTIR ESTE
	

GET_CHANNEL_FROM_A:
	AND %01100000
	RLCA
	RLCA
	RLCA
	RET
	
LIGA_NOISE:
	LD IX,VOL0 ;; VAMOS ESCOLHER O CANAL COM MAIOR VOLUME
LN_LOOP:
	LD A,(IX)
	LD D,(IX+1)
	LD E,(IX+2)
	CP D
	JR C,STEP1		; D … MAIOR QUE A
	CP E
	JR C,STEP1		; E … MAIOR QUE A
	LD B,%10110000	; NOISE VAI PARA O CANAL 0 (A)
	LD C,%00000001
	LD D,8			; VOLUME DO CANAL A
	JR LN_FIM
STEP1:				; A FOI DESCARTADO
	LD A,D
	CP E
	JR C,STEP3		; E … MAIOR QUE D
	LD B,%10011000	; NOISE VAI PARA O CANAL 2 (C)
	LD A,E
	LD C,%00000100
	LD D,9			; VOLUME DO CANAL B
	JR LN_FIM
STEP3:
	LD B,%10101000	; NOISE VAI PARA O CANAL 1 (B)
	LD A,D
	LD C,%00000010
	LD D,10			; VOLUME DO CANAL C
LN_FIM:
					; AQUI, A TEM VOLUME DO CANAL COM MAIOR VOLUME. TB TENHO B, COM A INFORMA«√O DE ONDE GUARDAR O NOISE E C, COM O CANAL TOM A DESLIGAR SE O VOLUME TOM FOR ZERO.
	CP $0			; 
	JR Z,TOM_VOLUME_ZERO	; SE O MAIOR TEM VOLUME ZERO, EU PRECISO AUMENTAR O VOLUME E DESLIGAR O TOM

LN_FIM2:
	LD	A,7
	OUT	($A0),A
	LD A,B
	OUT ($A1),A
	LD (REG7),A
	RET

TOM_VOLUME_ZERO:
	LD A,B
	;OR C
	LD B,A		; ARRUMEI B
	LD A,D		; VAMOS ENFIAR BALA NO VOLUME DO TOM (QUE AGORA VAI SER S” NOISE)
	OUT ($A0),A
	LD A,%00000110	; $6 de volume no noise
	OUT ($A1),A
	JR LN_FIM2

DESLIGA_NOISE:
	LD	A,7
	OUT	($A0),A
	LD A,%10111000	; DESABILITA NOISE EM TODOS OS CANAIS
	OUT ($A1),A
	LD (REG7),A
	RET

OUTPUT_CHANNEL:
	LD A,(LATCH)
	CALL GET_CHANNEL_FROM_A
	CP %00000011		; EH O DE RUIDO?
	JR Z,OUTPUT_RUIDO
	RLCA
	LD C,A				; C TEM O CANAL*2
	LD B,$0
	LD HL,TON0L
	ADD HL,BC			; HL TEM O CANAL CORRETO A GRAVAR
	LD A,C
	OUT ($A0),A			; SELECIONOU REGISTRADOR 0, 2 OU 4 DO PSG
	LD A,(HL)
	OUT ($A1),A			; GRAVEI
	INC C
	INC HL
	LD A,C
	OUT ($A0),A			; SELECIONOU REGISTRADOR 1, 3 OU 5 DO PSG
	LD A,(HL)
	OUT ($A1),A			; GRAVEI
	JP TS_FIM
		
OUTPUT_RUIDO:
	LD HL,TONN
	LD A,6
	OUT ($A0),A
	LD A,(HL)
	OUT ($A1),A
	JP TS_FIM	
	
Login or register to post comments
My MSX profile