2. Программа работы со звуковыми процессорами для игровой приставки SEGA MEGA DRIVE 2.1. Программа для основного процессора * * Программа, демонстрирующая работу с сопроцессором Z80 * и звуковыми процессорами приставки SEGA MEGA DRIVE * org $0 * Заголовок картриджа. dc.l $00FFFE00,$200,$200,$200,$200 dc.l $200 ,$200 ,$200, $200 ,$200, $200, $200 ,$200 dc.l $200 ,$200, $200, $200, $200 ,$200, $200 ,$200 dc.l $200, $200, $200, $200, $200, $200, $200 dc.l $200,$200,$200,$200,$200 dc.l $200, $200, $200, $200, $200, $200, $200, $200 dc.l $200, $200, $200, $200, $200, $200, $200 dc.l $200, $200, $200, $200, $200, $200, $200, $200 dc.l $200,$200,$200,$200,$200,$200,$200 dc.l $200 dc.b 'SEGA GENESIS (C)SEGA 1996 MAY' dc.b ' SAMPLE SOUND PROGRAM dc.b ' SAMPLE SOUND PROGRAM dc.b 'GM 00000000-00',$a5,$fb dc.b 'JD ' ,$00,$00,$00,$00,$00,$02,$00,$00 dc.b $00,$ff ,$00,$00,$ff ,$ff ,$ff ,$ff,' dc.b ' dc.b ' dc.b " JUE * Процедура обработки исключения. Ничего не делает, rte * Начало программы. .START tst.l $а10008.l bne.s SkipJoyDetect tst.w $al000c.l SkipJoyDetect: bne SkipSetup lea Table(pc),a5 movem.w (a5)+,d5-d7 movem.l (a5)+,a0-a4 move.b -$10ff(a1),d0 ; Проверка версии, andi.b #$0f,d0 beq.s WrongVersion move.l #$53454741,$2f00(a1) ; Код приставки (SEGA). WrongVersion: move.w (a4),d0 moveq #$00,d0 movea.l d0,a6 move a6,usp moveq #$17,dl ; Программирование регистров приставки. FillLoop: move.b (a5)+,d5 move.w d5,(a4) add.w d7,d5 dbra dl,FillLoop move.l (a5)+,(a4) move.w d0,(a3) move.w d7,(a1) move.w d7,(a2) L0250: Btst d0,(al) bne.s L0250 moveq #$25,d2 Filla: move.b (a5)+, (a0) + dbra d2,Filla move.w d0,(a2) move.w d0,(al) move.w d7,(a2) L0262: move.l d0,-(а6) dbra d6,L0262 move.l (a5)+,(a4) move.l (a5)+,(a4) moveq #$lf,d3 Filc0: move.l d0,(a3) dbra d3,Filc0 move.l (a5)+,(a4) moveq #$13,d4 Fillc1: move.1 d0,(a3) dbra d4, Fillc1 moveq #$03,d5 Fillc2: move.b (a5)+,$0011(a3) dbra d5,Fillc2 move.w d0,(a2) movem.l (a6),d0-d7/a0-a6 move #$2700,sr SkipSetup: bra.s Continue ; Вся аппаратура проинициализирована. Table: dc.w $8000, $3fff, $0100, $00a0, $0000, $00a1, $1100, $00a1 dc.w $1200, $00c0, $0000, $00c0, $0004, $0414, $302c, $075c dc.w $0000, $0000, $0000, $002c, $0001, $0000, $00ff, $ff00 dc.w $0080, $4000, $0080, $af01, $d91f, $1127, $0021, $2600 dc.w $f977, $edb0, $dde1, $fde1, $ed47, $ed4f, $dlel, $fl08 dc.w $d9c1, $d1e1, $f1f9, $f3ed, $5636, $e9e9, $8104, $8f01 dc.w $c000, $0000, $4000, $0010, $9fbf, $dfff * Загрузка программы в память сопроцессора. Continue: move.w #$100, $а11100 ; Остановка сопроцессора. move.w #$100,$а11200 ; Генерация сигнала сброса. lea Z80Driver,a0 ; Копирование программы. lea $a00000,al move.w #Z80DriverLen,d0 Z801oop: move.b (a0)+,(a1)+ subq.w #1,d0 bne Z80loop move.w #$0,$alll00 ; Разрешение работы сопроцессора. * Начало воспроизведения звука. move.l #Sega_Sound,d0; Определение адреса move.l #Sega_Len,d1 ; воспроизводимого фрагмента. bsr PlaySample Forever: nop ; Бесконечный цикл, во время nор ; выполнения которого bra Forever ; сопроцессор воспроизводит музыку. *_ * * Подпрограмма устанавливает параметры, необходимые * сопроцессору для формирования звука * * Входные данные * _ * d0 = адрес звуковых данных * d1 = размер блока звуковых данных * *_ PlaySample: move.w #$100,$а11100 ; Остановка сопроцессора. lea $а00039,а0 ; Запись флага, разрешающего воспроизведение, move.b #1,(а0)+ ; по адресу $39 в памяти Z80. move.b d0,(a0)+ ; Запись адреса блока звуковых данных lsr.l #8,d0 ; в памяти центрального процессора. move.b d0,(а0)+ lsr.l #8,d0 move.b d0,(a0)+ move.b d1,(a0)+ ; Запись длины блока, lsr.l #8,d1 move.b d1,(a0)+ lsr.l #8,d1 move.b d1,(a0) move.w #$0,$alll00 ; Разрешение работы Z80. rts *_ * Программа для процессора Z80 * Здесь эта программа приведена в виде кодов, * текст на ассемблере представлен ниже *_ Z80Driver: dc.b $с3, $46, $00, $00, $00, $00, $00 ,$00 dc.b $00 ,$00, $00, $00, $00, $00, $00, $00 dc.b $00,$00,$00,$00,$00,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$00,$00,$00 dc.b $00,$00,$00,$00,$00,$00,$00, $00 dc.b $00, $00, $00, $00, $00, $00, $00, $00 dc.b $00, $00, $00, $00, $00, $00, $00, $00 dc.b $c9, $01, $00, $00, $00, $00, $00, $00 dc.b $0 0,$00,$00,$00,$00,$00,$f3,$ed dc.b $56,$31,$00,$20,$3a,$39,$00,$b7 dc.b $ca, $4c, $00, $21, $3a, $00 , $11, $40 dc.b $00,$01,$06,$00,$ed,$b0,$3e,$00 dc.b $32,$39,$00,$3e,$b4,$32,$02,$40 dc.b $3e,$c0,$32,$03,$40,$3e,$2b,$32 dc.b $00,$40,$3e,$80,$32,$01,$40,$3a dc.b $43,$00,$4f , $3a, $44 , $00 , $47 , $3e dc.b $06,$3d,$c2,$81,$00,$21,$00,$60 dc.b $3a,$41,$00,$07,$77,$3a,$42,$00 dc.b $77,$0f ,$77,$0f ,$77,$0f ,$77,$0f dc.b $77,$0f ,$77,$0f ,$77,$0f ,$77,$3a dc.b $40,$00,$6f ,$3a,$41,$00,$f6,$80 dc.b $67,$3e,$2a,$32,$00,$40,$7e,$32 dc.b $01, $40 , $21, $40, $00, $7e, $c6, $01 dc.b $77,$23,$7e,$ce,$00,$77,$23,$7e dc.b $ce,$00,$77,$3a,$3 9,$00,$b7,$c2 dc.b $4c,$00,$0b,$7 8,$bl,$c2,$7f ,$00 dc.b $3a,$45,$00,$b7,$ca,$4c,$00,$3d dc.b $3a,$45,$00,$06,$ff ,$0e,$ff , $c3 dc.b $7f,$00 Z80DriverEnd: Z80DriverLen equ Z80DriverEnd - Z80Driver Sega_Sound: *_ * * Здесь располагаются звуковые данные, * которые будут воспроизводиться. Пример блока * звуковых данных можно найти в файле sound.asm * *_ Sega_Sound_End: Sega_Len equ Sega_Sound_End - Sega_Sound .end 2.2. Программа для сопроцессора Z80 .org $0 ;Программа воспроизведения звука ;для сопроцессора Z80 ;игровой приставки SEGA MEGA DRIVE sound_driver: jp start_driver ; Точка запуска, .fill $35,0 ; Буфер. ret ; Точка входа в процедуру ; обработки прерывания. ; Переменные, которые инициализирует центральный ; процессор перед началом воспроизведения. start_flag: ; Если 0, звук не воспроизводится, .byte 0 in_addr: ; Адрес начала звуковых данных. .byte 0,0,0 in_len: ; Длина звуковых данных. .byte 0,0,0 ; Сюда процессор Z80 копирует параметры блока, addr: ; Адрес начала звуковых данных. .byte 0,0,0 len: ; Длина звуковых данных. .byte 0,0,0 ; Текст программы start_driver: di im 1 ld sp,$2000 ; Установка указателя стека. main_loop: ld a,(start_flag); Ожидание разрешения начать or a ; воспроизведение звука, jp z,main_loop ld hl,in_addr ; Копирование данных блока, ld de,addr ; который будет воспроизводиться. ld bc,$6 ldir ld a,0 ld (start_flag),a ld а,$b4 ; Инициализация звукового процессора. ld ($4002),a ; Разрешение стереозвучания. ld a,$c0 ld ($4003),a ld a,$2b ; Разрешение работы ЦАП. ld ($4000),a ld a,$80 ld ($4001) ,a ld a,(len) ; Загрузка в ВС длины блока аудиоданных. ld с, а ld а,(len+1) ld b,a sound_loop: ld a,$6 wait: dec a jp nz,wait ld hi,$6000 ; Поразрядная запись ld a, (addr+1) ; адреса блока звуковых данных rlca ; в регистр, управляющий доступом ld (hi),а ; к памяти основного процессора. ld a,(addr+2) ld (hl),а rrca ld (hl),a rrca ld (hl),a rrca ld (hl),a rrca ld (hl),a rrca ld (hl),a rrca ld (hl),a rrca ld (hi),a ld a,(addr) ; Теперь страница памяти ld l,a ; центрального процессора доступна для Z80 ld a, (addr+1) ; по адресу 8000h. or $80 ld h, а ld a,$2a ; Запись байта в ЦАП. ld ($4000),а ld a,(hl) ld ($4001) ,а ld hl,addr ; Увеличение адреса. ld a,(hl) add a,1 ld (hl),a inc hl ld a,(hl) adc a,0 ld (hl),a inc hl ld a,(hl) adc a,0 ld (hl),a ld a,(start_flag) ; Нужно ли воспроизводить or a ; звуковой фрагмент jp nz,main_loop ; перед завершением? dec be ld a,b or с jp nz,sound_loop ; Воспроизведение завершено? ld a,(len+2) or a jp z,main_loop ; Да. dec a ld a,(len+2) ld b,$ff ld c,$ff jp sound_loop ; Нет, следующий блок. .end |