home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Sound
/
DeliTrackerII
/
Bonus
/
PlayAY100.lha
/
PlayAY
/
dev
/
src
/
ZXAYEMUL.S
< prev
next >
Wrap
Text File
|
1996-02-29
|
12KB
|
613 lines
;---------------T
******** Z80 Emul AY Player, (C) 1994-2000 Patrik Rak - Raxoft ********
******************** Part of PlayAY distribution **********************
* 1.0 original release
* 1.1 added support for AMSTRAD (I think)
* 1.2 first 256 bytes are filled with 201 (so JP 56 and like is possible)
* (except the launch sequence, of course)
* 1.2a fixed behavior of AMSTRAD CPC port handling
* 1.3 CPC frequencies were an octave higher!
* 1.4 Process changed to Task (RemTask()ing a process leaked memory)
AMSTRAD equ 1 ;emulate also AMSTRAD CPC peripherals
COLOROUT equ 0 ;map border (out 254) as $dff180
DEBUG equ 0
ifne DEBUG
bsr.w initplayer
tst.l d0
bne.b error
lea test(pc),a0
bsr.w initsound
bsr.w interrupt
bsr.w endsound
bsr.w endplayer
error rts
test dc.b 0,1,2,3
dc.w 1000
dc.w 100
dc.w $1234
dc.w testl-*
dc.w testb-*
testl dc.w 40000 ;stack
dc.w 0 ;init
dc.w 49152 ;interrupt
testb dc.w 32768
dc.w 1
dc.w testc1-*
dc.w 49152
dc.w 9
dc.w testc2-*
dc.w 0
testc2 dc.b 62,0 ;ld a,0
dc.b 61 ;dec a
dc.b 50,1,$c0 ;ld ($c001),a
dc.b 211,254 ;out (254),a
testc1 dc.b $ed,0,201 ;bug,rts
even
endc
**** Include stuff ****
incdir include:
; include exec/funcdef.i
include exec/exec_lib.i
include exec/execbase.i
include exec/memory.i
include exec/tasks.i
include dos/dos_lib.i
include dos/dos.i
include dos/var.i
include dos/dostags.i
incdir deliay:dist/dev/src/include40/
include misc/AYPlayer.i
include misc/mine.i
incdir deliay:
include z80.i
incdir ''
***** How single EMUL_Song looks like ******
STRUCTURE EMUL_Song,0
UBYTE ems_assignA ;0-3 specifies, what amiga channel will be
UBYTE ems_assignB ;assigned to each ay channel (A-C, noise)
UBYTE ems_assignC
UBYTE ems_assignN
UWORD ems_songlen ;how long the song is in VBIs
UWORD ems_fadelen ;how many VBIs to fade
UWORD ems_initnumber ;this will be stored to HL,DE,BC,IX,IY,A (MSB)
;and all ' registers before calling ems_init
RPTR ems_launch ;Allows same Launch with different initnumbers
RPTR ems_firstblock ;which block(s) install to z80 RAM.
LABEL ems_sizeof
STRUCTURE EMUL_Launch,0
UWORD eml_stack ;what will be loaded into SP register
UWORD eml_init ;Routine which set ups the player.
;if zero, use ems_firstblock->emd_address
;or use $1b just for calling ret instruction
UWORD eml_interrupt ;to what address jump to do one VBI play
;if zero, (I*$100+$FF) will be used
LABEL eml_sizeof
STRUCTURE EMUL_Block,0
UWORD emd_address ;or null for last block in table
UWORD emd_length ;simply said: take block at emd_binary
RPTR emd_binary ;emd_length bytes long and install it in Z80
LABEL emd_sizeof ;RAM at emd_address
**** Real start **********
dd AYPLAYERHEADER EMUL
dc.b 0 ;no transpose + terminator for GetVar
AYbase ds.l 1 ;where ay registers should be "outed"
AYass ds.l 1 ;where ay channel assignment should be copied
AYfreq ds.l 1 ;we ignore this anyway
dc.w initplayer-*
dc.w endplayer-*
dc.w initsound-*
dc.w endsound-*
dc.w interrupt-*
dc.w 0,0 ;no patterns
name dc.b 'Z80 Emul Player 1.4',0
dc.b 'Unknown - original Z80 code is running',0
dc.b '(C) 1994-2000 Patrik Rak - Raxoft',0
dosn dc.b 'dos.library',0
even
;Allocate memory for RAM and Emulator, and install both. Report failure
;in d0 (0=OK)
initplayer
exec a6
lea b(pc),a5
moveq #37,d0
lea dosn(pc),a1
jsrlib OpenLibrary
move.l d0,dosb-b(a5)
beq.b endplayer
moveq #-8,d4 ;8 byte pod romkou jako rezerva na stack
swap d4 ;jeden staci, ale nejaky potize s allocabs...
move.l #zxsize,d2
bsr.w Alloc64k
beq.b endplayer
addq.l #8,d0
move.l d0,zxbase-b(a5)
moveq #0,d4
move.l #emullen,d2
bsr.w Alloc64k
beq.b endplayer
move.l d0,emulbase-b(a5)
move.l d0,a4
move.l d0,a1
lea emulator(pc),a0
move.l #emullen,d0
jsrlib CopyMem
jsrlib CacheClearU ;Flush the Caches
btst #AFB_68010,AttnFlags+1(a6)
beq.b .keepmovesrdx
jsr z80_MODE68010(a4)
jsrlib CacheClearU ;flush caches
.keepmovesrdx
lea z80_out(a4),a1
lea out(pc),a0
move.l a0,(a1)+ ;out
lea return(pc),a0
move.l a0,(a1)+ ;in
move.l a0,(a1)+ ;ldir delay
move.l a0,(a1) ;lddr delay
moveq #0,d0
return rts
;Free the memory.
endplayer
exec a6
lea b(pc),a5
move.l zxbase(pc),d0
beq.b .nozx
subq.l #8,d0
move.l d0,a1
move.l #zxsize,d0
jsrlib FreeMem
clr.l zxbase-b(a5)
.nozx
move.l emulbase(pc),d0
beq.b .noz80
move.l d0,a1
move.l #emullen,d0
jsrlib FreeMem
clr.l emulbase-b(a5)
.noz80
move.l dosb(pc),d0
beq.b .nodos
move.l d0,a1
jsrlib CloseLibrary
clr.l dosb-b(a5)
.nodos moveq #-1,d0
rts
;Install channel asignement
;Install data to the RAM
;then run the emulator
initsound
exec a6
lea b(pc),a5
move.l AYass,a1
move.l (a0)+,(a1) ;assignement
move.l (a0)+,(a5)+ ;songlen+fadelen
clr.l (a5)+ ;ay_selected(2)+ay_regs(14)=16 bytes
clr.l (a5)+
clr.l (a5)+
clr.l (a5)+
move.l (a5),a1 ;zxbase
move.l #$c9c9c9c9,d1
move.w #256/4-1,d0 ;fill begin of rom with ret (201)
.rom0 move.l d1,(a1)+
dbra d0,.rom0
moveq #-1,d1
move.w #$3f00/4-1,d0 ;fill rom with 255
.rom move.l d1,(a1)+
dbra d0,.rom
moveq #0,d1
move.w #$c000/4-1,d0 ;fill ram with 0
.ram move.l d1,(a1)+
dbra d0,.ram
move.b #243,(a1) ;di
move.l (a5)+,a3 ;zxbase
move.l (a5)+,a4 ;emulbase
move.l (a0),d1 ;ems_initnumber<<16!ems_initnumber
move.w (a0)+,d1
move.l a0,a1 ;launch
add.w (a0)+,a1
move.l a0,a2 ;block
add.w (a0),a2
lea z80_pc(a4),a0
clr.w (a0)+ ;reset pc to zero
move.w (a1)+,(a0)+ ;set sp to eml_stack
move.l d1,(a0)+ ;af,af'
move.l d1,(a0)+ ;bc,bc' to ems_initnumber
move.l d1,(a0) ;ix,iy
move.l d1,z80_d(a4) ;de,hl
move.l d1,z80_d_(a4) ;de',hl'
move.b #$cd,(a3)+ ;call install z80 startup code
move.w (a1)+,d0 ;eml_init
bne.b .useit
move.w (a2),d0 ;emb_address
.useit
move.b d0,(a3)+ ;lsb
move.w d0,(a3)+ ;msb
move.b #$21,-1(a3) ;ld hl,
move.b 1(a1),(a3)+ ;eml_interrupt lsb
move.b (a1),(a3)+ ;msb
moveq #z80launchlen-1,d0
.launch move.b (a5)+,(a3)+
dbra d0,.launch
.copy move.l a3,d1 ;zxbase+something
move.w (a2)+,d1 ;emb_address
beq.b .copydone
move.l d1,a1 ;zxbase+emb_address
moveq #0,d0
move.w (a2)+,d0
move.l a2,a0
add.w (a2)+,a0
add.w d1,d0 ;if address+len > 65536
bcc.b .ok
moveq #0,d0 ;protect the innocent
.ok sub.w d1,d0
jsrlib CopyMem
bra.b .copy
.copydone
move.l (a5)+,a6 ;dosbase
lea var(pc),a0
move.l a0,d1
lea priority(pc),a4
move.b #127,(a4) ;set pri to maximum
move.l a4,d2
moveq #2,d3 ;because of bug in V37 (nullterm)
move.l #GVF_BINARY_VAR,d4
jsrlib GetVar
exec a6
lea memlist(pc),a0
jsrlib AllocEntry
bclr.l #31,d0
bne.b .nomem
move.l d0,a1
move.l taskmem-memlist(a1),a3
move.l stackmem-memlist(a1),d1
move.l d1,TC_SPLOWER(a3)
add.l stacksize-memlist(a1),d1
move.l d1,TC_SPUPPER(a3)
move.l d1,TC_SPREG(a3)
move.b #NT_TASK,LN_TYPE(a3)
move.b (a4),LN_PRI(a3)
lea name(pc),a0
move.l a0,LN_NAME(a3)
lea TC_MEMENTRY(a3),a0
NEWLIST a0
jsrlib AddHead
move.l a3,a1
lea entry(pc),a2
sub.l a3,a3
jsrlib AddTask
move.l d0,(a5) ;task (or NULL in case of failure)
.nomem rts
;stop the emulator and dump the regs if error was encountered
endsound exec a6
move.l task(pc),d0
beq.b .none
move.l d0,a1
jsrlib RemTask
.none
lea dosb(pc),a0
move.l (a0)+,a6 ;dosbase
clr.l (a0)+ ;task
move.l (a0),d7 ;emulator exit code
beq.b .exit ;no error
clr.l (a0)+
move.l a0,d1 ;debugname
move.l #MODE_NEWFILE,d2
jsrlib Open
move.l d0,d6
beq.b .exit ;nochance
move.l emulbase(pc),a5
move.l a7,a2
lea z80_i(a5),a4
move.l (a4),d0
lsr.l #8,d0
and.w #$ff,d0
push d0 ;r,i
move.l -(a4),-(sp) ;ix,iy
lea z80_which(a5),a3
add.w (a3),a3 ;correct exx set
move.w 2(a3),d0 ;other set
move.w (a3,d0),-(sp) ;hl'
move.w (a3),-(sp) ;hl
move.w -2(a3,d0),-(sp) ;de'
move.w -(a3),-(sp) ;de
move.l -(a4),-(sp) ;bc,bc'
move.l -(a4),-(sp) ;af,af'
move.l -(a4),-(sp) ;pc,sp'
lea zxbase(pc),a0
push (a0)+ ;zxbase
push (a0) ;emulbase
push d7 ;return code from emulator
lea format(pc),a0
move.l d6,d1
move.l a0,d2
move.l a7,d3
jsrlib VFPrintf
move.l a2,a7
move.l d6,d1
jsrlib Close
.exit rts
;Copy AY registers to AY, then signal Interrupt received to the emulator.
;(Freqs multiplied by 8 (or 16 for CPC)).
;Return fadelen or 0 in d0.
interrupt
exec a6
lea ay_regs(pc),a0
move.l AYbase(pc),a1
moveq #3-1,d1
ifne AMSTRAD
move.b multiplyshift(pc),d2
.freqs move.w (a0)+,d0
ror.w d2,d0 ;swap bytes & multiple word appropriatelly
else
.freqs move.w (a0)+,d0
ror.w #8-3,d0 ;swap bytes & multiple word by 8
endc
move.w d0,(a1)+ ;copy first six bytes
dbra d1,.freqs
move.l (a0)+,(a1)+ ;+4
move.l (a0),(a1) ;+4 = 14 registers
move.l task(pc),d0 ;if no task then exit
beq.b .exit
move.l d0,a1
move.l #SIGBREAKF_CTRL_C,d0
jsrlib Signal
lea songlen(pc),a0
moveq #0,d0
tst.w (a0)
beq.b .exit
subq.w #1,(a0)+
bne.b .exit
move.w (a0),d0
.exit rts
************************* Support routines *********************
Alloc64k moveq #MEMF_FAST!MEMF_PUBLIC,d3
bsr.b .main
bne.b .exit
moveq #MEMF_CHIP!MEMF_PUBLIC,d3
;d2 size, d3 type of mem, d4 word allignment (eg. -1 will allocate $xxxxffff)
; in upper word
.main lea MemList(a6),a2
.loop move.l (a2),a2
move.l (a2),d0
beq.b .exit
move MH_ATTRIBUTES(a2),d0
and d3,d0
cmp d3,d0
bne.b .loop
move.l d4,d0
move.w MH_LOWER(a2),d0
bra.b .in
.loop2 swap d0
addq #1,d0
.in swap d0
cmp.l MH_UPPER(a2),d0
bcc.b .loop
move.l d0,a1
push d0
move.l d2,d0
jsrlib AllocAbs
tst.l d0
popm d0
beq.b .loop2
.exit rts
****************************** Z80 out routine ***********************
out
ifne COLOROUT
btst #0,d1
bne.b .nofe
and #7,d0
add.w d0,d0
lea .tab(pc,d0.w),a0
move.w (a0),$dff180
rts
.tab dc.w $000
dc.w $00f
dc.w $f00
dc.w $f0f
dc.w $0f0
dc.w $0ff
dc.w $ff0
dc.w $fff
endc
.nofe
cmp.w #$fffd,d1
bne.b .notselect
cmp.b #14,d0
bcc.b .exit
.outregamstrad move.b d0,ay_selected+1
.exit rts
.notselect
cmp.w #$bffd,d1
bne.b .notdata
lea ay_regs(pc),a0
add.w ay_selected(pc),a0
move.b d0,(a0)
ifne AMSTRAD
move.b #8-3,multiplyshift
rts
.notdata
clr.b d1
cmp.w #$f600,d1
bne.b .notcontrolport
move.b d0,d1
move.b porta(pc),d0
add.b d1,d1
bcc.b .exit
bmi.b .outregamstrad
lea ay_regs(pc),a0
move.w ay_selected(pc),d1
cmp.b #14,d1
bcc.b .exit
add.w d1,a0
move.b d0,(a0)
move.b #8-4,multiplyshift
rts
.notcontrolport
cmp.w #$f400,d1
bne.b .notdataport
move.b d0,porta
.notdataport
rts
else
.notdata
rts
endc
************************** variables ************************
ifne AMSTRAD
porta dc.b 0
multiplyshift dc.b 8-3 ; 8-3 for ZX, 8-4 for CPC
endc
;warning - do not change the order of variables!!! used in initsound!
b
songlen dc.w 0
fadelen dc.w 0
ay_selected dc.w 0 ;to which ay register we are going to "out"
ay_regs dc.w 0,0,0 ;freqs
dc.b 0 ;noise
dc.b 0 ;strobe
dc.b 0,0,0 ;volumes
dc.b 0 ;envtype
dc.b 0,0 ;envfreq
zxbase dc.l 0
emulbase dc.l 0
*************************** Z80 launch code ***********************
z80launch
; dc.b $cd ;call xx
;init dc.b 0,0
; dc.b $21 ;ld hl,xx
;rupt dc.b 0,0
dc.b $7c ;ld a,h
dc.b $b5 ;or l
dc.b $20,$08 ;jr nz,ok
dc.b $ed,$57 ;ld a,i
dc.b $67 ;ld h,a
dc.b $2d ;dec l
dc.b $5e ;ld e,(hl)
dc.b $23 ;inc hl
dc.b $56 ;ld d,(hl)
dc.b $eb ;ex de,hl
dc.b $22,$17,0;ok ld (here+1),hl
dc.b $76 ;loop halt
dc.b $cd,0,0 ;here call xx
dc.b $18,$fa ;jr loop
dc.b 201 ;ret
z80launchlen equ *-z80launch
********************* Emulator Task Data *********************
dosb dc.l 0
task dc.l 0
exitcode dc.l 0
dc.b 'RAM:'
var dc.b 'Z80debug',0
format dc.b 'Error: %08lx Emulator: %08lx RAM: %08lx',10,10
dc.b 'PC:%04x SP :%04x',10
dc.b 'AF:%04x AF'':%04x',10
dc.b 'BC:%04x BC'':%04x',10
dc.b 'DE:%04x DE'':%04x',10
dc.b 'HL:%04x HL'':%04x',10
dc.b 'IX:%04x IY :%04x',10
dc.b 'I : %02x R : %02x',10
dc.b 0
priority dc.b 127,0 ; extra 0 because of nullterm bug in v37
even
memlist ds.b LN_SIZE
dc.w 2
taskmem dc.l MEMF_PUBLIC!MEMF_CLEAR
dc.l TC_SIZE
stackmem dc.l MEMF_PUBLIC!MEMF_CLEAR
stacksize dc.l 4096
entry lea zxbase(pc),a0
move.l (a0)+,d7 ;zxbase
move.l (a0),a0 ;emulbase
jsr z80_RUN(a0)
lea exitcode(pc),a0 ;hopefully, this never gets executed
move.l d7,(a0) ;return code from emulator
exec a6
.loop moveq #0,d0
jsrlib Wait
bra.b .loop ;never reached
*********************** z80 emulator *************************
emulator incbin 'deliay:Z80' ;sorry, not distributed :-)
emullen equ *-emulator
zxsize equ 8+65536+8