org #8000
nolist ; ; Digitalised sample loader by roudoudou/Flower Corp. ; First sample loader ever RELEASED on Amstrad CPC first generation! ; ; Sorry Shap, i waited 20 years to see yours, here is mine ;) ; This is a beta release, there will be improvements in a few months ; edouard (.) berge (at) gmail (.) com ; ; documentation: ; SOS programmeurs 1,2,3,4 ; Quasar.CPCScene.net ; Amslive (Madram) ; Disc+Ultra notice ; ; ; main functions in the example ; ; FDC_SetSectorSize (default 2, may use from 0 to 5) ; FDC_SetDrive (default 0) ; FDC_MotorON ; FDC_MotorOFF ; FDC_PlaySampleInit ; play a sample at approx 3.9Khz ; FDC_CalibrateSample ; FDC_SetTrackSample ; FDC_ReadSectorSample ; FDCMainStateDataAvailable EQU 128 FDCMainStateWay EQU 64 ; 1 -> output to Z80 / 0 -> input from Z80 FDCMainStateIsData EQU 32 ; 1 -> instr in progress 0 -> result to fetch FDCMainStateIsBusy EQU 16 ; 1 -> instr in progress / 0 -> FDC Ready FDCMainStateWaitSeekDriveD EQU 8 FDCMainStateWaitSeekDriveC EQU 4 FDCMainStateWaitSeekDriveB EQU 2 FDCMainStateWaitSeekDriveA EQU 1 FDCMainStateWaitSeek EQU 1+2+4+8 FDCET0StateCurrentOperation EQU 192 ; 00 OK 01 KO ou RW ended 10 illegal instruction 11 no floppy / drive lost ; 11 ejected disk while operating on it ; 01 / 00 -> OK FDCET0StateNoDisk EQU 128 ; 1 -> no disk FDCET0StateEndOfInstruction EQU 32 ; 1 -> instruction terminated FDCET0StateElectronicERROR EQU 16 ; calibrating failed or electronic error FDCET0StateDriveUnplugged EQU 8 ; drive or head unavailable FDCET0StateSelectedHead EQU 4 FDCET0StateActiveDrive EQU 3 FDCET1StateEndOfTrack EQU 128 ; reached end of track FDCET1StateCRCError EQU 32 ; or wrong read IDs FDCET1StateDataTimingKO EQU 16 ; respect the 26us specifications!!! Z80 was too slow! FDCET1StateSectorNotFound EQU 4 ; or cannot read ID FDCET1StateProtectedFloppy EQU 2 ; when trying to write/format FDCET1StateIDSNotFound EQU 1 ; wrong format FDCET2StateErasedSectorFound EQU 64 FDCET2StateReadWriteError EQU 32 ; checksum error in data red FDCET2StateWrongIdTrack EQU 16 ; in sector definition FDCET2StateDataCompareOK EQU 8 FDCET2StateDataCompareKO EQU 4 FDCET2StateWrongIdTrackBis EQU 2 ; id track == #FF FDCET2StateDAMNotFound EQU 1 ; wrong format FDCET3StateUnknownSpecificDrive EQU 128 ; drive out of order FDCET3StateProtectedFloppy EQU 64 ; FDCET3StateInsertedFloppy EQU 32 ; drive and floppy ready FDCET3StateHeadInTrack0 EQU 16 FDCET3StateDoubleHeadDisable EQU 8 ; 1 -> single head / 0 -> double head FDCET3StateSelectedHead EQU 4 FDCET3StateSelectedDrive EQU 3 ;--------------------------- sample test --------------------------------- ; disable system di ld hl,#C9FB ld (#38),hl ld sp,#200 ; B=video mode ; C=screen width in bytes ld bc,#0150 call BB5A_Setup ; HL=sample adress ; DE=sample length ld hl,#2000 ld de,6903 call FDC_PlaySampleInit ; Setup FDC library ld a,2 call FDC_SetSectorSize xor a call FDC_SetDrive call FDC_MotorON ; ; THOSE TWO FUNCTIONS ARE NOT AVAILABLE IN THE V035 RELEASE ; ;call FDC_CheckConnectedDrive ;call FDC_TestHardwareIsOK ; check hardware conflicts ; ; force drive A without hardware check / for testing purpose!!! ld hl,FDC_DriveEnabled ld (hl),1 inc hl call FDC_CalibrateSample ;------------------------- infinite test loop ----- ReTrack ld a,1 ; read track from 1 to 38 TestSetTrack push af call FDC_SetTrackSample or a jr z,FDC_LibError ld de,#C1C9 ld hl,#6000 call FDC_ReadSectorSample or a jr z,FDC_LibError pop af inc a cp 39 jr c,TestSetTrack TestSetTrackDec push af call FDC_SetTrackSample or a jr z,FDC_LibError ld de,#C1C9 ld hl,#6000 call FDC_ReadSectorSample or a jr z,FDC_LibError pop af dec a jr nz,TestSetTrackDec jr ReTrack ;------------------------- end of infinite test loop ----- ; brutal stop at first error! FDC_LibError call FDC_DisplayError call FDC_MotorOFF jr $ ;-------------------- FDC LIBRARY / LOGICAL CORE -------------------------------------------- ; ; define maximum track for current drive ; may be use to allow track greater than 41 ; on 3.5' drive ; FDC_SetMaxTrack push hl cp 82 jr c,FDC_SetMaxTrackOK ld hl,MSG_InvalidSetMaxTrack jp FDC_LibError FDC_SetMaxTrackOK push af ld hl,FDC_MaxTrack ; get MaxTrack adress of selected drive ld a,(FDC_Drive) add l ld l,a pop af ld (hl),a pop hl ret ; ; Set library sector size from 0 to 5 ; FDC_SetSectorSize cp 6 jr nc,FDC_SetSectorSizeError ld (FDC_SectorSize),a ret FDC_SetSectorSizeError ld hl,MSG_SectorSizeError jp FDC_LibError FDC_GetSectorSize ld a,(FDC_SectorSize) ret FDC_SetHead and #1 ld (FDC_Head),a ret FDC_GetHead ld a,(FDC_Head) ret FDC_SetDrive and #3 ld (FDC_Drive),a ; @TODO return an error if not 0->3 ret FDC_GetDrive ld a,(FDC_Drive) ret FDC_DisableCurrentDrive push hl push af ld hl,FDC_DriveEnabled ld a,(FDC_Drive) add l ld l,a ld (hl),0 ; disable drive pop af pop hl ret FDC_EnableCurrentDrive push hl push af ld hl,FDC_DriveEnabled ld a,(FDC_Drive) add l ld l,a ld (hl),1 pop af pop hl ret FDC_GetCurrentTrack push hl ld hl,FDC_CurrentTrack ld a,(FDC_Drive) add l ld l,a ld a,(hl) pop hl ret ; FDC_CheckAllowedDrive ; if the drive is disabled then this function ; will return back to previous function call FDC_CheckAllowedDrive push af push hl ld a,(FDC_Drive) ld hl,FDC_DriveEnabled add l ld l,a ld a,(hl) or a jr nz,FDC_CheckAllowedDriveOK pop hl pop af ld (FDC_CheckAllowedDriveHLBack+1),hl pop hl FDC_CheckAllowedDriveHLBack: ld hl,#1234 ; restore HL ret FDC_CheckAllowedDriveOK pop hl pop af ret ; Compute ending value of HL after a read/write command ; then call FDC_ReadWriteCheckHL after read/write to check ; the operation was successfull ; ; HL=destination buffer ; D=start sector ; E=end sector ; FDC_ReadWriteComputeFinalHL push af push de push hl ; compute sector size in bytes ld hl,64 ld a,(FDC_SectorSize) inc a FDC_RWCSS add hl,hl dec a jr nz,FDC_RWCSS ld a,e sub d inc a ; number of sector to read/write FDC_RWCSTR ex hl,de ld hl,0 FDC_RWCSTR2Loop add hl,de dec a jr nz,FDC_RWCSTR2Loop ex hl,de ; de=total size to read/write pop hl push hl add hl,de ; final value of HL after a successfull read/write ld (FDC_RWSectorCompare+1),hl pop hl pop de pop af ret ; Check HL value after read/write command ; return ; A=1 if OK ; A=0 if KO ; HL=error message NULL terminated ; FDC_ReadWriteCheckHL push de push hl ex hl,de FDC_RWSectorCompare: ld hl,#1234 xor a sbc hl,de ld a,h or l jr z,FDC_ReadWriteCheckHLOK ld hl,MSG_IncompleteRW xor a pop de pop de ret FDC_ReadWriteCheckHLOK ld a,1 pop hl pop de ret ;---------- ERROR DISPLAY -------------- FDC_DisplayError push af push hl display_max:ld a,24 dec a ld (display_max+1),a or a jr z,$ call FDC_DisplayErrorLoop ld a,13 call BB5A push bc ld b,#f5 in a,(c) rra jr nc,$-3 pop bc pop hl pop af ret ; FDC_DisplayErrorLoop ld a,(hl) or a ret z call BB5A ; simple display inc hl jr FDC_DisplayErrorLoop ;-------------- TIMEOUT MANAGEMENT -------------------- ; ; Init a maximum value of a timeout counter ; FDC_InitTimeOutFull push hl ld hl,0 ld (FDC_TimeOutValue+1),hl pop hl ret ; ; Fine tuning for a timeout counter ; A=approx 1/10s of delay wanted ; FDC_InitTimeOut push hl push de ld hl,0 ld de,390 FDC_InitTimeOutSimpleMUL add hl,de dec a jr nz,FDC_InitTimeOutSimpleMUL ld (FDC_TimeOutValue+1),hl pop de pop hl ret ; ; decrement timer then set A ; A=1 -> time out! ; A=0 -> no time out FDC_CheckTimeOut push hl FDC_TimeOutValue: ld hl,#1234 dec hl ld (FDC_TimeOutValue+1),hl ld a,l or h ld a,0 jr nz,FDC_CheckTimeOutIsOK ld hl,MSG_OperationTimeOut call FDC_DisplayError ld a,1 FDC_CheckTimeOutIsOK pop hl ret ;-------------------- FDC LIBRARY / HARDWARE CORE -------------------------------------------- FDC_MotorON push af push bc ld a,(FDC_MotorState) or a jr nz,FDC_MotorSkipDelay inc a FDC_MotorGeneric ld bc,#FA7E out (c),a ld (FDC_MotorState),a or a jr z,FDC_MotorSkipDelay ld b,200 ei halt djnz $-1 di FDC_MotorSkipDelay pop bc pop af ret FDC_MotorOFF push af push bc xor a jr FDC_MotorGeneric FDC_MotorState defb 0 ; first byte ; ; look for connected but turned off additionnal drives ; may be used instead of only calibrating! ; ; ; NOT FINISHED !!! ; ; FDC_CheckConnectedDrive push af push bc push hl call FDC_GetDrive push af xor a call FDC_SetDrive call FDC_CalibrateSample ld hl,FDC_DriveEnabled ld (hl),1 ; et si il etait KO ce lecteur hein? inc hl FDC_CheckConnectedDriveLoop ld a,1 call FDC_SetDrive call FDC_CalibrateSample ld a,(FDCET0State) and FDCET0StateCurrentOperation cp #80 ; INVALID COMMAND jr nz,FDC_CheckConnectedDriveOK ld hl,MSG_PlugDriveB call FDC_DisplayError ld (hl),0 jr FDC_CheckConnectedDriveKO FDC_CheckConnectedDriveOK ld (hl),1 FDC_CheckConnectedDriveKO pop af call FDC_SetDrive ; set last drive used pop hl pop bc pop af ret ; ; ; NOT FINISHED !!! ; ; ; test ET0 and ET3 FDC_TestHardwareIsOK push af push hl call FDC_GetInterruptStateSample ; ld a,(FDCET0State) and FDCET0StateElectronicERROR jr z,FDC_TestHardwareIsOKNext01 ld hl,MSG_ElectronicError call FDC_DisplayError call FDC_DisableCurrentDrive jr FDC_TestHardwareIsOKEND FDC_TestHardwareIsOKNext01 ld a,(FDCET0State) and FDCET0StateDriveUnplugged jr z,FDC_TestHardwareIsOKNext02 ld hl,MSG_DriveUnplugged call FDC_DisplayError call FDC_DisableCurrentDrive jr FDC_TestHardwareIsOKEND FDC_TestHardwareIsOKNext02 ; check ET3 if IntState succeed call FDC_GetDriveStateSample ld a,(FDCET3State) or FDCET3StateInsertedFloppy jr nz,FDC_TestHardwareIsOKNext03 ld hl,MSG_InsertFloppy call FDC_DisplayError FDC_TestHardwareIsOKNext03 FDC_TestHardwareIsOKEND pop hl pop af ret FDC_ReadWriteManageError push hl ld a,(FDCET0State) and FDCET0StateNoDisk jr z,$+2+3+2 ld hl,MSG_InsertFloppy jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET0State) and FDCET0StateElectronicERROR jr z,$+2+3+2 ld hl,MSG_ElectronicError jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET0State) and FDCET0StateDriveUnplugged jr z,$+2+3+2 ld hl,MSG_DriveUnplugged jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET1State) and FDCET1StateCRCError jr z,$+2+3+2 ld hl,MSG_CRCErrorWrongID jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET1State) and FDCET1StateDataTimingKO jr z,$+2+3+2 ld hl,MSG_YourTooSlow jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET1State) and FDCET1StateSectorNotFound jr z,$+2+3+2 ld hl,MSG_SectorNotFound jr FDC_ReadWriteManageErrorKO ; test protected floppy? for what? ; ld a,(FDCET1State) and FDCET1StateIDSNotFound jr z,$+2+3+2 ld hl,MSG_WrongFormat jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET2State) and FDCET2StateReadWriteError jr z,$+2+3+2 ld hl,MSG_ChecksumError jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET2State) and FDCET2StateWrongIdTrack jr z,$+2+3+2 ld hl,MSG_WrongIdTrack jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET2State) and FDCET2StateWrongIdTrackBis jr z,$+2+3+2 ld hl,MSG_WrongIdTrack jr FDC_ReadWriteManageErrorKO ; ld a,(FDCET2State) and FDCET2StateDAMNotFound jr z,$+2+3+2 ld hl,MSG_WrongDAMFormat jr FDC_ReadWriteManageErrorKO pop hl ld a,1 ret FDC_ReadWriteManageErrorKO pop af ; remove HL from stack xor a ret ;------ FDC GET -------- ; ; HL=adress to store result, will be incremented ; returns ; A=1 if OK / HL=HL+1 ; A=0 if cannot read FDC_GetByte push bc ld bc,#FB7E FDC_GetByteWaitForIt in a,(c) jp p,FDC_GetByteWaitForIt ; test bit 7 and FDCMainStateIsBusy jr z,FDC_GetByteBusy inc c in a,(c) ld (hl),a inc hl pop bc ld a,1 ret FDC_GetByteBusy pop bc xor a ret ;------ FDC SEND -------- FDC_FastSendByte push bc push af ld bc,#FB7E FDC_FastSendByteWaitFDC in a,(c) jp p,FDC_FastSendByteWaitFDC ; test bit 7 inc c pop af out (c),a ld b,4 djnz $ pop bc ret FDC_SendByte push bc push af ld bc,#FB7E FDC_SendByteWaitFDC in a,(c) add a jr nc,FDC_SendByteWaitFDC add a jr nc,FDC_SendByteExpected ; put value in the message pop af ld hl,MSG_FDCDoNotWantData+1 call BB5A_PutDigit dec hl call FDC_DisplayError ; cannot send byte to FDC! pop bc ret FDC_SendByteExpected pop af inc c out (c),a ld b,4 djnz $ pop bc ret ; ; HL=command bytes ; B=command length ; FDC_SendCommand ld a,(hl) call FDC_SendByte inc hl djnz FDC_SendCommand ret ;********************************************************************************************** ; FDC FUNCTIONS THAT CAN PLAY A LOOPED SAMPLE DURING OPERATIONS... ;********************************************************************************************** ; ; command #4 returns ET3 ; FDC_GetDriveStateSample call FDC_WaitToBeReadySample push af push hl ld a,#4 call FDC_SendByte ld a,(FDC_Drive) call FDC_SendByte ld hl,FDCET3State call FDC_GetByte pop hl pop af ret FDC_WaitToBeReadySample push hl push bc push af call FDC_InitTimeOutFull FDC_IsNotReadySample call FDC_PutPSGOneSample ; play sample, maybe too fast? ld b,15 djnz $ call FDC_CheckTimeOut or a jr nz,FDC_IsReadyTimeoutSample ld bc,#FB7E in a,(c) jp p,FDC_IsNotReadySample ;ld c,a ;and FDCMainStateWaitSeek ; seek still in progress? ;jr nz,FDC_IsNotReadySample ;ld a,c and FDCMainStateIsBusy jr nz,FDC_IsNotReadySample ; Wait FDC is Ready FDC_IsReadyExitSample pop af pop bc pop hl ret FDC_IsReadyTimeoutSample call FDC_DisableCurrentDrive jr FDC_IsReadyExitSample FDC_GetInterruptStateSample call FDC_WaitToBeReadySample push af push de push hl call FDC_InitTimeOutFull FDC_GetInterruptStateSampleLoop call FDC_PutPSGOneSample call FDC_CheckTimeOut or a jr nz,FDC_GetInterruptStateOKSample ; timeout ld a,#8 call FDC_SendByte ; ld hl,FDCET0State call FDC_GetByte ld hl,FDC_CurrentTrack ld a,(FDC_Drive) ld d,0 ld e,a add hl,de ; hl=currenttrack of currentdrive call FDC_GetByte ; may return nothing if seeking or a jr z,FDC_GetInterruptStateSampleLoop ld a,(FDCET0State) and FDCET0StateEndOfInstruction jr z,FDC_GetInterruptStateSampleLoop ; wait until current operation end ld a,(FDCET0State) and FDCET0StateCurrentOperation cp #80 jr nz,FDC_GetInterruptStateTestInsertedFloppySample ld hl,MSG_InvalidCommand call FDC_DisplayError call FDC_DisableCurrentDrive jr FDC_GetInterruptStateOKSample ; exit on first error FDC_GetInterruptStateTestInsertedFloppySample ld a,(FDCET0State) and FDCET0StateDriveUnplugged jr z,FDC_GetInterruptStateOKSample ld hl,MSG_DriveUnplugged call FDC_DisplayError call FDC_DisableCurrentDrive FDC_GetInterruptStateOKSample pop hl pop de pop af ret FDC_CalibrateSample call FDC_WaitToBeReadySample push af push bc push hl ld a,#7 call FDC_SendByte ld a,(FDC_Drive) call FDC_SendByte ; ID-Drive without useless head ; call FDC_GetInterruptStateSample ; check piste 0 ld hl,FDC_CurrentTrack ld d,0 ld e,a add hl,de ; hl=currenttrack of currentdrive ld a,(hl) or a jr z,FDC_CalibrateOKSample ld hl,MSG_CannotCalibrate call FDC_DisplayError jr $ FDC_CalibrateOKSample pop hl pop bc pop af ret ; ; SET TRACK WHILE PLAYING SAMPLE ; ; input ; A=desired track ; ; output ; A=1 -> OK ; ; A=0 -> KO ; HL=error message NULL terminated ; FDC_SetTrackSample call FDC_CheckAllowedDrive call FDC_WaitToBeReadySample push de push hl call FDC_PutPSGOneSample ; PLAY SAMPLE ld d,a ld (FDC_SetTrackTargetSample+1),a ld a,2 ld (FDC_SetTrackRetrySample+1),a ; retry 2 times max dec a ld (FDC_SetTrackRetryCalibrateSample+1),a ; calibrate one time then error ld hl,FDC_MaxTrack ; get MaxTrack of selected drive ld a,(FDC_Drive) ld e,a ld a,d ld d,0 add hl,de cp (hl) jr c,FDC_SetTrackNextSample ld hl,MSG_InvalidTrackNumber xor a jr FDC_SetTrackEndSample ; FDC_SetTrackNextRedoSample ld a,2 ld (FDC_SetTrackRetrySample+1),a FDC_SetTrackNextSample ; entry loop ld a,#F ; command call FDC_SendByte ld a,(FDC_Drive) ; drive call FDC_SendByte ld a,(FDC_SetTrackTargetSample+1) ; track call FDC_SendByte ; call FDC_GetInterruptStateSample ; check piste bien celle demandee ld a,(FDC_CurrentTrack) FDC_SetTrackTargetSample: cp #12 jr z,FDC_SetTrackOKSample ; RETRY FDC_SetTrackRetrySample: ld a,#12 dec a ld (FDC_SetTrackRetrySample+1),a jr nz,FDC_SetTrackNextSample ; RETRIES FAILED CALIBRATE! call FDC_CalibrateSample FDC_SetTrackRetryCalibrateSample: ld a,#12 dec a ld (FDC_SetTrackRetryCalibrateSample+1),a jr nz,FDC_SetTrackNextRedoSample ld hl,MSG_CannotSetTrack xor a jr FDC_SetTrackEndSample ; FDC_SetTrackOKSample ld a,1 FDC_SetTrackEndSample pop hl pop de ret ; ; Get 7 bytes after executing general command ; ; output ; A=1 OK ; A=0 KO ; HL=error message NULL terminated ; FDC_GetResult7BytesSample push hl push de call FDC_PutPSGOneSample ; PLAY SAMPLE ; result 7 bytes ld hl,FDCET0State call FDC_GetByte ; ET0 call FDC_GetByte ; ET1 call FDC_GetByte ; ET2 ld hl,FDC_CurrentTrack ld a,(FDC_Drive) ld d,0 ld e,a add hl,de call FDC_GetByte ; get current track for current drive ld hl,FDC_Head call FDC_GetByte ld hl,FDC_ResultSectorID call FDC_GetByte ; 'unused' ld hl,FDC_ResultSectorSize call FDC_GetByte ; 'unused' ; pop de pop hl call FDC_ReadWriteManageError ret ; READ SECTOR WHILE PLAYING SAMPLE ; ; input ; HL=destination buffer ; D=start sector ; E=end sector ; ; output ; A=1 OK ; HL=destination buffer+size read ; or ; A=0 KO ; HL=error message NULL terminated ; FDC_ReadSectorSample call FDC_CheckAllowedDrive call FDC_WaitToBeReadySample call FDC_ReadWriteComputeFinalHL ld (ReadBufferSample+1),hl ; call FDC_PutPSGOneSample ; PLAY SAMPLE ; command ld a,#46 call FDC_SendByte ld a,(FDC_Drive) call FDC_SendByte ld hl,FDC_CurrentTrack add l ld l,a ld a,(hl) ; track call FDC_SendByte ld a,(FDC_Head) call FDC_SendByte ld a,d call FDC_SendByte ld a,(FDC_SectorSize) call FDC_SendByte ld a,e call FDC_SendByte ld a,#20 call FDC_SendByte ; GAP unused? xor a call FDC_SendByte ; length unused? ; execution ReadBufferSample: ld hl,#1234 call FDC_GenericReadDataSAMPLE call FDC_PlaySampleResync ; MANDATORY after executing state machine! call FDC_GetResult7BytesSample or a ret z call FDC_ReadWriteCheckHL or a ret z ret ;*************** FDC STATE MACHINE TO READ DATA **************************************************************** ; ; input HL start of destination array ; returns HL end of data red ; FDC_GenericReadDataSAMPLE push bc push de ld bc,#FB7E ld d,FDCMainStateIsData call FDC_GenericReadDataLoopSample pop de pop bc ret ; ; play a sample routine algo (QuasarCPC) ; out #F4xx,9 ; channel B volume register ; out #F6xx,#C0 ; PSG must read register ; out #F6xx,0 ; PSG inactive ; out #F4xx,v ; value to write to the register ; out #F6xx,#80 ; PSG must read value ; out #F6xx,0 ; PSG inactive ; ; assuming those registers before calling ; D=9 ; E=0 ; C=#C0 -> res 6,C -> #80 -> set 6,C -> #C0 ; B=#F4 -> set 1,B -> #F6 -> res 1,B -> #F4 ; ; ; Init secondary registers for sample replay ; ; HL=sample adress ; DE=sample length FDC_PlaySampleInit push hl add hl,de ld a,h ld (FDC_PutPSG_HEND+1),a ld (FDC_PutPSG_OS_HEND+1),a pop hl ld a,h ld (FDC_PutPSG_LoopReinit+1),a ld (FDC_PutPSG_OS_LoopReinit+1),a ld de,#900 ld bc,#F4C0 exx ld bc,#F700 ld a,#82 out (c),a ; Port A en sortie xor a dec b out (c),a ; reset command ; ; configure default PSG output ; ld hl,#73F ;%00111111 init channel mixer/noise call PSGPutValue ld hl,#800 call PSGPutValue ld hl,#A00 call PSGPutValue ret ; H=psg register ; L=value PSGPutValue push bc push de ld de,#C080 ld bc,#F400 out (c),h out (c),d out (c),c out (c),l out (c),e out (c),c pop de pop bc ret ; ; After reading data we do not know which state we were ; so we need to reinit values! Except HL ; FDC_PlaySampleResync exx ld de,#0900 ld bc,#F6C0 out (c),e ; PPI inactive for sure res 1,b exx ret ;------------- unrolled FDC read + SAMPLE replay ------------- FDC_GenericReadDataLoopSample in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl FDC_GenericReadDataLoopSamplePSG1 exx out (c),d ; #09 channel B volume register set 1,b out (c),c ; #C0 exx ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl exx xor a out (c),a ; #00 (ACK) res 1,b res 6,c ; #C0 -> #80 exx ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl exx ld e,(hl) inc hl exx ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl exx out (c),e ; sample value set 1,b out (c),c ; #80 exx ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl exx out (c),e ; #00 (ACK) res 1,b set 6,c ld a,h exx ex af,af' ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ex af,af' FDC_PutPSG_HEND: cp #12 ; H-end jr nz,FDC_PutPSG_GOK exx FDC_PutPSG_LoopReinit: ld h,#12 exx FDC_PutPSG_GOK ; before we loop, wait a little in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,$+11 and d ret z inc c in a,(c) dec c ld (hl),a inc hl ; in a,(c) jp p,FDC_GenericReadDataLoopSamplePSG1 and d ret z inc c in a,(c) dec c ld (hl),a inc hl jp FDC_GenericReadDataLoopSample ;---------- all in one PLAY SAMPLE subroutine FDC_PutPSGOneSample exx ex af,af' xor a out (c),d ; #09 channel B volume register set 1,b out (c),c ; #C0 out (c),a ; #00 dec b res 6,c ; #C0 -> #80 outi ; dec b ; out (c),(hl) ; inc hl set 1,b out (c),c ; #80 out (c),a ; #00 res 1,b set 6,c ld a,h FDC_PutPSG_OS_HEND: cp #12 ; H-end jr nz,FDC_PutPSG_OS_OK FDC_PutPSG_OS_LoopReinit: ld h,#12 FDC_PutPSG_OS_OK ex af,af' exx ret ; ; standard routines, read,write,format,advanced format ; do not need to be published... ; ; read 'FDC_library_extension_v001.asm' ; ; FDC_Advanced_Command (not used) FDC_multitrack defb 0 ; bit 7 FDC_density defb 1 ; bit 6 FDC_ignore_ds defb 0 ; bit 5 ; FDC_Advanced_Drive_Settings FDC_Head defb 0 ; bit 2 FDC_Drive defb 0 ; bit 0/1 FDC_SectorSize defb 2 FDC_SectorNumber defb 9 ; Amsdos default 9 FDC_SectorFirstID defb #C0 ; Amsdos default #C0 FDC_SectorGap defb #52 ; Amsdos default #52 FDC_FillValue defb #5A ; Amsdos default = #E5 FDC_ResultSectorID defb 0 FDC_ResultSectorSize defb 0 align 4 FDC_MaxTrack defb 41,41,41,41 ; software limitation, maybe raised up! FDC_CurrentTrack defb -1,-1,-1,-1 FDC_DriveEnabled defb 0,0,0,0 ; FDC_State mirror FDCMainState defb 0 FDCET0State defb 0 FDCET1State defb 0 FDCET2State defb 0 FDCET3State defb 0 ; Library messages MSG_OperationTimeOut defb 'FDC OPERATION TIMEOUT',0 MSG_CannotSetTrack defb 'CANNOT SET TRACK',0 MSG_CannotCalibrate defb 'CANNOT CALIBRATE DRIVE',0 MSG_InvalidCommand defb 'INVALID FDC COMMAND',0 MSG_SectorSizeError defb 'INVALID SECTOR SIZE',0 MSG_DisableDrive defb 'DRIVE DISABLED',0 MSG_InvalidTrackNumber defb 'REQUESTED TRACK TOO HIGH',0 MSG_InvalidSetMaxTrack defb 'MAXTRACK VALUE TOO HIGH',0 MSG_IncompleteRW defb 'READ/WRITE ABORTED DURING OPERATION',0 MSG_WTBR_Purge defb '( ) PURGE STACK DURING WAIT TO BE READY',0 ; Main State specific messages MSG_FDCDoNotWantData defb '( ) FDC IS NOT EXPECTING DATA',0 ; ET0 specific messages MSG_ElectronicError defb 'DRIVE IS REPORTING INTERNAL FAILURE',0 MSG_DriveUnplugged defb 'DRIVE OR HEAD UNAVAILABLE',0 MSG_PlugDriveB defb 'TURN ON DRIVE B OR DISCONNECT IT',0 MSG_InsertFloppy defb 'INSERT FLOPPY',0 ; ET1 specific messages MSG_CRCErrorWrongID defb 'CRC ERROR',0 MSG_YourTooSlow defb 'Z80 WAS TOO SLOW TO GET DATA',0 MSG_SectorNotFound defb 'SECTOR NOT FOUND',0 MSG_WrongFormat defb 'WRONG FORMAT',0 ; ET2 specific messages MSG_ChecksumError defb 'CHECKSUM ERROR IN DATA',0 MSG_WrongIdTrack defb 'WRONG ID TRACK IN SECTOR DEF',0 MSG_WrongDAMFormat defb 'WRONG DAM FORMAT',0 ; ET3 specific messages MSG_DriveOutOfOrder defb 'DRIVE OUT OF ORDER',0 MSG_ProtectedFloppy defb 'FLOPPY IS PROTECTED',0 read 'BB5A_replacement_v001.asm' read 'sampletest_unpacked_6903.asm' |