Merlin 16+ Source

*

* sound driver demo

*

 lst off

 xc

 xc

 rel

 cas in

 dsk /devel/projects/snddemo/snddemo.L

 use 1/tool.equates/e16.gsos

 use 4/util.macs ; pushword, pushlong

 use 4/misc.macs

 use 4/locator.macs

 use 4/mem.macs

 use 4/qd.macs

 use 4/qdaux.macs

 use 4/event.macs

 use 4/window.macs

 use 4/ctl.macs

 use 4/menu.macs

 use 4/desk.macs

 use 4/gsos.macs

 use 4/sound.macs

*-----------------------------------------------------------------------------

* DP variables and local equates

*-----------------------------------------------------------------------------

 dum $0000

AppMMID ds 2,0  ; Memory Manager ID

HndlRef ds 2,0  ; For Dereferencing MM Handle

DPBase ds 1,0  ; Deref'd handle

BuffPtr ds 2,0  ; $4000 bytes for sound

 dend

*-----------------------------------------------------------------------------

* GS/OS Program Entry Point

*-----------------------------------------------------------------------------

Entry mx %00

 phk

 plb

 brl Main

*

* Check for toolbox errors

* too-simple error handler

*

CheckError

 bcs SysDeath

 rts

SysDeath pha

 pushlong #0000

 _SysFailMgr

*

* StartUpTools - start up the various toolsets

*

StartUpTools 

 _TLStartUp

 pha

 _MMStartUp

 jsr CheckError

 pullword AppMMID

 _MTStartUp

  

 pha

 pha

 pushlong #$700     ; 7 pages of DP space

 pushword AppMMID

 pushword #$C005     ; Fixed, Page-Aligned, Locked, Unpurgeable

 pushlong #$000000    ; in Bank $00, $0000

 _NewHandle

 jsr CheckError

 pulllong HndlRef

 lda [HndlRef]

 sta DPBase

 pha      ; save dp pointer for later

 pha

 pushword #$0080     ; Screen Mode ($0000 = 320, $0080 = 640)

 pushword #$00A0     ; Pixel Map Size ($0050 = 320, $00A0 = 640)

 pushword AppMMID

 _QDStartUp

 jsr CheckError

 pla                 ; saved dp pointer

 clc

 adc #$300

 pha                    ; save dp pointer for later

 pha

 pushword #20         ; Event Queue size

 pushword #0         ; Min X clamp

 pushword #640         ; Max X clamp

 pushword #0         ; Min Y clamp

 pushword #200         ; Max Y clamp

 pushword AppMMID

 _EMStartUp

 jsr CheckError

  

 pushword #0

 _SetBackColor

  

 pushword #3

 _SetForeColor

  

 pushword #50        ; X position

 pushword #85        ; Y position

 _MoveTo

  

 pushlong #OneMoment

 _DrawCString

  

 pushlong #ToolList

 _LoadTools

 jsr CheckError

  

 pushword AppMMID

 _WindStartUp

 jsr CheckError

  

 pla                    ; saved dp pointer

 clc

 adc #$100

 pha                    ; save it for later

 tax                    ; save dp pointer in x

 pushword AppMMID

 phx

 _CtlStartUp

 jsr CheckError

  

 pla

 clc

 adc #$100

 pha

 tax

 pushword AppMMID

 phx

 _MenuStartUp

 jsr CheckError

  

 _DeskStartUp

 jsr CheckError

 pla

 clc

 adc #$100

 pha

 _SoundStartUp

 jsr CheckError

 rts

*

* ShutDownTools - shut em back down

*

ShutDownTools 

 lda ToolList

 asl

 asl

 tax

 lda ToolList-2,x

 cmp #$2      ; Memory Manager?

 bne ShutDownOne     ; Nope, do it normally

 pushword AppMMID

 _DisposeAll

 pushword AppMMID

 lda #$2      ; set up for toolset #2 (MM)

ShutDownOne   

 ora #$300      ; Call #3 (Shutdown)

 tax

 jsl $E10000

 dec ToolList

 bne ShutDownTools

 rts

*

* Main - main sequence of events

*

Main jsr StartUpTools

 jsr PrepDeskTop

 sep $20

 ldal $e0c034

 sta ScreenColorByte

 lda #00

 stal $e0c034

 rep $30

* corner rounding

 pushword #0000

 _SetForeColor

* upper left

 pushword #0001

 pushword #0000

 _MoveTo

 pushword #0001

 pushword #0002

 _LineTo

 pushword #0002

 pushword #0000

 _MoveTo

 pushword #0002

 pushword #0001

 _LineTo

 pushword #0003

 pushword #0000

 _MoveTo

 pushword #0003

 pushword #0000

 _LineTo

* upper right

 pushword #0638

 pushword #0000

 _MoveTo

 pushword #0638

 pushword #0002

 _LineTo

 pushword #0637

 pushword #0000

 _MoveTo

 pushword #0637

 pushword #0001

 _LineTo

* lower left

 pushword #0000

 pushword #0195

 _MoveTo

 pushword #0000

 pushword #0199

 _LineTo

 pushword #0001

 pushword #0197

 _MoveTo

 pushword #0001

 pushword #0199

 _LineTo

 pushword #0002

 pushword #0199

 _MoveTo

 pushword #0002

 pushword #0199

 _LineTo

* lower right

 pushword #0639

 pushword #0195

 _MoveTo

 pushword #0639

 pushword #0199

 _LineTo

 pushword #0638

 pushword #0197

 _MoveTo

 pushword #0638

 pushword #0199

 _LineTo

 pushword #0637

 pushword #0199

 _MoveTo

 pushword #0637

 pushword #0199

 _LineTo

EventLoop     

 jsr Maint      ; Music maintenance if it's playing

 pha       ; Result Space

 pushword #$ffff      ; Event Mask

 pushlong #EventRec

 _TaskMaster

 pla

 beq EventLoop

  

 cmp #$11        ; wInMenuBar?

 bne EventLoop   ; no, so ignore

  

 jsr MenuDispatch

 bit QuitFlag

 bpl EventLoop

  

 sep $20

 lda ScreenColorByte

 stal $e0c034

 rep $30

 jsr ShutDownTools

 iGSOS _Quit;QParams;1

*

* Prepare Desktop

*

PrepDeskTop  

 pushlong #0000

 _RefreshDesktop

 _InitCursor

NextMenu pha

 pha

 lda MenuTbl

 asl

 tax

 lda MenuTbl,x

 phb

 phb

 pha

 _NewMenu

 pushword #0000

 _InsertMenu

  

 dec MenuTbl

 bne NextMenu

  

 pushword #1

 _FixAppleMenu

  

 pha

 _FixMenuBar

 pla

  

 _DrawMenuBar

 rts

*

* Apple Menu: About

*

About rts

*

* File Menu: Quit

*

Quit dec QuitFlag

 rts

*

* Play the noise

*

Play jsr init

 rts

*

* Menu Dispatcher

*

MenuDispatch 

 lda TaskData

 and #$00ff

 asl

 tax

 jsr (MenuDispatchTbl,x)

  

 pushword #0000

 pushword TaskData+2

 _HiliteMenu

 rts

*

* Non-DP Variables

*

QuitFlag     

 dw 00,00

ScreenColorByte     

 dw 00

*

* Tool List

*

ToolList     

 dw 10    ; Tool Count

 dw 01,00    ; Tool Locator, any vers

 dw 02,00    ; Memory Manager, any vers

 dw 03,00    ; Misc Tools, any vers

 dw 04,00    ; QuickDraw II, any vers

 dw 06,00    ; Event Manager, any vers

 dw 14,00    ; Window Manager, any vers

 dw 16,00    ; Control Manager, any vers

 dw 15,00    ; Menu Manager, any vers

 dw 05,00    ; Desk Manager, any vers

 dw 08,00    ; Sound Manager, any vers

ToolListEnd

*

* Menu Structures

*

MenuDispatchTbl   

 dw About

 dw Quit

 dw Play

MenuTbl dw 4        ; count

 dw Menu1

 dw Menu2

 dw Menu3

 dw Menu4

MenuTblEnd

Menu1 asc '>>@\XN1'00

 asc '--About This Program...\N256*??'00

 asc '---\D'00

 asc '>'

Menu2 asc '>>  File  \N2'00

 asc '--Quit\N257*Qq'00

 asc '>'

Menu3 asc '>>  Edit  \N3D'00

 asc '--Undo\N250V*Zz'00

 asc '--Cut\N251*Xx'00

 asc '--Copy\N252*Cc'00

 asc '--Paste\N253V*Vv'00

 asc '--Clear\N254'00

 asc '>'

Menu4 asc '>>  Music  \N4'00

 asc '--Play\N258*Pp'00

 asc '>'

*

* Event Record

*

EventRec

Event_What   

 ds 2

Event_Msg    

 ds 4

Event_When

 ds 4

Event_Where

 ds 4

Event_Mods

 ds 2

TaskData 

 ds 4

TaskMask 

 dw $1fff,$0000

*

* Strings

*

OneMoment

 asc 'One Moment Please...'00

*

* GS/OS Quit Params

*

QParams ds 4

 ds 4

*

* apple iigs streaming sound driver

* based on OVERSAMPLER

* christopher shepherd <cshepher@ieee.org>

* june 2007

*

init

 ldx #$4000

 ldy #0000

 jsr Alloc

 jsr checkError

 stx HndlRef

 sty HndlRef+2

 lda [HndlRef]

 sta BuffPtr

 ldy #0002

 lda [HndlRef],y

 sta BuffPtr+2

 jsr DOCHalt

 pushLong #SoundMIRQV

 _SetSoundMIRQV

 jsr checkError

player

 jsr DOCInit

 jsr FileOpen

 jsr FirstDiskRead

 ldy #0000

]pl1 lda RegTbl2,y

 cmp #$FFFF

 beq ]pl2

 and #$00FF

 tax

 lda RegTbl2,y

 xba

 and #$00FF

 jsr SetDOCReg

 iny

 iny

 bra ]pl1

]pl2 ldx EchoDelay

 beq ]noecho

]vbl sep $20

]vbl1 ldal $E0C019

 bpl ]vbl1

]vbl2 ldal $E0C019

 bpl ]vbl2

 rep $20

 dex

 bne ]vbl

]noecho ldx #$00A0 ; A0 - Control 0

 lda #0000 ; 00 - free run, no int, no halt (playing)

 jsr SetDOCReg

 stz BadIntCount

 stz SndBank

 stz EndFlag

 lda #$FFFF

 sta IntFlag

 lda EndFlag

 bne ]end2

Maint

 lda IntFlag

 beq NextChunk

]mret rts

NextChunk

 dec IntFlag

 jsr DiskRead

 bcs ]end2

 ldx SndBank

 jsr PutSndData

 lda SndBank

 eor #0001

 sta SndBank

 lda IntFlag

 bne ]mret

* interrupt happened during refilling (too slow!)

 inc BadIntCount

 lda BadIntCount

 cmp #0003

 beq ]end2

 bra ]mret

]end2

 jsr DOCHalt

 rts

RegTbl2

 db $00,$01 ; freq low0   = E3

 db $20,$02 ; freq high0  = 01 (freq0 = 1E3 or d483)

 db $10,$01 ; freq low16  = E3

 db $30,$02 ; freq high16 = 01 (freq16 = 1E3 or d483)

 db $08,$01 ; freq low8   = E3

 db $28,$02 ; freq high8  = 01 (freq8 = 1E3 or d483)

 db $40,$FF ; volume0     = FF

 db $50,$FF ; volume16    = FF

 db $48,$00 ; volume8     = 00

 db $80,$00 ; addr0       = 00

 db $88,$80 ; addr8       = 80

 db $90,$00 ; addr16      = 00

 db $C0,$3F ; multi0      = 3F (play 32k sound)

 db $C8,$3E ; multi8      = 3E (play 32k sound, half resolution)

 db $D0,$3F ; multi16     = 3F (play 32k sound)

 db $A0,$01 ; control0    = 01 (free run, halt, no int)

 db $A8,$08 ; control8    = 08 (free run, no halt, int)

 db $B0,$10 ; control16   = 10 (free run, no halt, no int, stereo?)

 db $FF,$FF ; end of table

* halt all DOC voices

DOCHalt ldx #$00A0

 lda #$0001

]dh jsr SetDOCReg

 inx

 cpx #$00C0

 bne ]dh

 rts

* read a DOC register

* a = data

* x = register

GetDOCReg

 sep $20

]busy ldal $E1C03C

 bmi ]busy

 ldal $E100CA

 and $0F

 stal $E1C03C

 txa

 stal $E1C03E

 ldal $E1C03D

 ldal $E1C03D

 rep $20

 rts

* set a DOC register

* a = data

* x = register

SetDOCReg

 sep $20

 pha

]busy2 ldal $E1C03C

 bmi ]busy2

 ldal $E100CA

 and $0F

 stal $E1C03C

 txa

 stal $E1C03E

 pla

 stal $E1C03D

 rep $20

 rts

* init DOC registers to defaults

DOCInit sep $20

 ldal $E100CA

 and #$0F

 ora #$60

 stal $E1C03C ; DOC RAM, auto-increment

 lda #00

 stal $E1C03E

 stal $E1C03F ; address $0000

 ldy #00

 lda #80

]base stal $E1C03D ; put $80 (baseline) into DOC RAM

 iny

 bne ]base

 rep $20

 ldy #0000

]init lda RegTbl1,y

 cmp #$FFFF

 beq ]ret

 and #$00FF

 tax

 lda RegTbl1,y

 xba

 and #$00FF

 jsr SetDOCReg

 iny

 iny

 bra ]init

]ret rts

RegTbl1

 db $00,$00  ; freq low0     = 00

 db $20,$08  ; freq hi0      = 08

 db $10,$00  ; freq low16    = 00

 db $30,$08  ; freq hi16     = 08

 db $08,$00  ; freq low8     = 00

 db $28,$08  ; freq hi8      = 00

 db $40,$00  ; volume 0      = 00

 db $50,$00  ; volume 16     = 00

 db $48,$00  ; volume 8      = 00

 db $80,$00  ; address low0  = 00

 db $88,$00  ; address low8  = 00

 db $90,$00  ; address low16 = 00

 db $C0,$00  ; wavtbl0       = 00

 db $C8,$00  ; wavtbl8       = 00

 db $D0,$00  ; wavtbl16      = 00

 db $A0,$00  ; control0      = 00

 db $A8,$00  ; control8      = 00

 db $B0,$00  ; control16     = 00

 db $FF,$FF  ; end of table

* slam data from buffer into DOC ram

* a, y - trashed

* $88 - pointer to the data

* x=0 - stash in DOC $0000

* x=1 - stash in DOC $4000

PutSndData

 sep $20

 ldal $E100CA

 and #$0F

 ora #$60 ; DOC RAM, auto increment

 stal $E1C03C

 lda #00

 stal $E1C03E ; address low byte: 00

 cpx #00

 beq ]hi

 lda #$40

]hi stal $E1C03F

 ldy #0000

]sloop lda [BuffPtr],y

 bne ]nozero

 inc

]nozero ldx OverSample

 beq ]noover

 jsr OverSample2x

]noover stal $E1C03D

 iny

 cpy RTrans

 bcc ]sloop

 cpy RReq

 beq ]ret2

 lda #00

 stal $E1C03D ; 00 byte for end of sound

]ret2 rep $20

 rts

OverSample2x

 cpx #0002

 beq OverSample4x

 pha

 rep $20

 clc

 adc OSByte2

 lsr

 sep $20

 stal $E1C03D

 pla

 sta OSByte2

 rts

OverSample4x

 pha

 rep $20

 clc

 adc OSByte2

 lsr

 sta OSByte1

 clc

 adc OSByte2

 lsr

 sep $20

 stal $E1C03D

 lda OSByte1

 stal $E1C03D

 pla

 sta OSByte2

 rep $20

 clc

 adc OSByte1

 lsr

 sep $20

 stal $E1C03D

 lda OSByte2

 rts

* Sound MIRQ handler

SoundMIRQV

 php

 phb

 phd

 rep $30

 phk

 plb

 lda OrigDataBank

 tcd

 ldx #$00E0 ; oscillator interrupt register

 jsr GetDOCReg

 bit #$0080 ; interrupt?

 beq ]smi1

 and #$003E ; get osc number

 cmp #$0010 ; oscillator8?

 bne ]smi1

 stz IntFlag ; clear interrupt flag to show this happened

]smi1 ldx #$00A0 ; Control Register 0

 jsr GetDOCReg

 and #0001 ; halted?

 beq ]smi2

 dec EndFlag

 jsr DOCHalt

]smi2 pld

 plb

 plp

 clc

 rtl

IntFlag dw $FFFF

EndFlag dw 0000

EchoDelay dw 0000

SndBank dw 0000

BadIntcount dw 0000

OverSample dw 0000

Length dw 0000

Length2 dw 0000

OSByte1 dw 0000

OSByte2 dw 0000

OrigDataBank dw 0000

* read a chunk from disk

* first time - fill low and high $4000's

FirstDiskRead

 lda #0000

 sta SDisp

 sta SDisp+2 ; init position to 0

 iGSOS _SetMark;SeekParams;1

 jsr CheckError

 ldx BuffPtr

 ldy BuffPtr+2

 stx RData

 sty RData+2 ; set GSOS to read to our allocated buffer

 lda #$4000

 ldx OverSample

 beq ]noOS

]OS lsr  ; reduce to $2000 or $1000 if 2x or 4x oversample

 dex

 bne ]OS

]noOS sta RReq

 stz RReq+2

 iGSOS _Read;ReadParams;1

 jsr CheckError

 ldx #0000

 jsr PutSndData

 iGSOS _Read;ReadParams;1

 jsr CheckError

 ldx #0001

 jsr PutSndData

 clc

 rts

* just get one chunk from disk

DiskRead

 iGSOS _Read;ReadParams;1

 clc

 rts

* open the file for reading

FileOpen

 iGSOS _Open;OpenParams;1

 jsr CheckError

 lda OHndl

 sta RHndl

 sta CHndl

 sta GHndl

 sta SHndl

 iGSOS _GetEOF;GetEOFParams;1

 jsr CheckError

 rts

OpenParams

 dw $0002

OHndl dw 0000

OPath adrl FilePath

FilePath strl 'demjeans.WAV'

ReadParams

 dw $0004

RHndl dw 0000

RData dw 0000

 dw 0000

RReq dw 0000

 dw 0000

RTrans dw 0000

 dw 0000

CloseParams

 dw $0001

CHndl dw 0000

GetEOFParams

 dw $0002

GHndl dw 0000

GEOF dw 0000

 dw 0000

SeekParams

 dw $0003

SHndl dw 0000

SBase dw 0000

SDisp dw 0000

 dw 0000

* Get Memory from the Memory Manager

* x = size lo

* y = size hi

Alloc pha

 pha

 phy

 phx

 pushword AppMMID

 pushword #$C000

 pushlong #$000000

 _NewHandle

 plx

 ply

 rts