/** * Handle word read access from IO memory. */ uae_u32 IoMem_wget(uaecptr addr) { Uint32 idx; Uint16 val; /* Check if access is made by a new instruction or by the same instruction doing multiple word accesses */ if ( IoAccessInstrPrevClock == CyclesGlobalClockCounter ) IoAccessInstrCount++; /* Same instruction, increase access count */ else { IoAccessInstrPrevClock = CyclesGlobalClockCounter; if ( ( table68k[ M68000_CurrentOpcode ].size == 1 ) && ( OpcodeFamily != i_MVMEL ) && ( OpcodeFamily != i_MVMLE ) ) IoAccessInstrCount = 0; /* Instruction size is word and not a movem : no multiple accesses */ else IoAccessInstrCount = 1; /* 1st access of a long or movem.w */ } addr &= 0x00ffffff; /* Use a 24 bit address */ if (addr < 0xff8000 || !regs.s) { /* invalid memory addressing --> bus error */ M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_WORD, BUS_ERROR_ACCESS_DATA); return -1; } if (addr > 0xfffffe) { fprintf(stderr, "Illegal IO memory access: IoMem_wget($%x)\n", addr); return -1; } IoAccessBaseAddress = addr; /* Store for exception frame */ nIoMemAccessSize = SIZE_WORD; nBusErrorAccesses = 0; idx = addr - 0xff8000; IoAccessCurrentAddress = addr; pInterceptReadTable[idx](); /* Call 1st handler */ if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx]) { IoAccessCurrentAddress = addr + 1; pInterceptReadTable[idx+1](); /* Call 2nd handler */ } /* Check if we completely read from a bus-error region */ if (nBusErrorAccesses == 2) { M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_WORD, BUS_ERROR_ACCESS_DATA); return -1; } val = IoMem_ReadWord(addr); LOG_TRACE(TRACE_IOMEM_RD, "IO read.w $%06x = $%04x pc=%x\n", addr, val, M68000_GetPC()); return val; }
/** * Write word to sound control register (0xff8900). * * FIXME: add Falcon specific handler here... */ void DmaSnd_SoundControl_WriteWord(void) { Uint16 nNewSndCtrl; HATARI_TRACE(HATARI_TRACE_DMASND, "DMA snd control write: 0x%04x\n", IoMem_ReadWord(0xff8900)); nNewSndCtrl = IoMem_ReadWord(0xff8900) & 3; if (!(nDmaSoundControl & DMASNDCTRL_PLAY) && (nNewSndCtrl & DMASNDCTRL_PLAY)) { //fprintf(stderr, "Turning on DMA sound emulation.\n"); DmaSnd_StartNewFrame(); } else if ((nDmaSoundControl & DMASNDCTRL_PLAY) && !(nNewSndCtrl & DMASNDCTRL_PLAY)) { //fprintf(stderr, "Turning off DMA sound emulation.\n"); } nDmaSoundControl = nNewSndCtrl; }
/** * Handle word read access from IO memory. */ uae_u32 IoMem_wget(uaecptr addr) { Uint32 idx; Uint16 val; addr &= 0x00ffffff; /* Use a 24 bit address */ if (addr < 0xff8000 || !regs.s) { /* invalid memory addressing --> bus error */ M68000_BusError(addr, BUS_ERROR_READ); return -1; } if (addr > 0xfffffe) { fprintf(stderr, "Illegal IO memory access: IoMem_wget($%x)\n", addr); return -1; } IoAccessBaseAddress = addr; /* Store for exception frame */ nIoMemAccessSize = SIZE_WORD; nBusErrorAccesses = 0; idx = addr - 0xff8000; IoAccessCurrentAddress = addr; pInterceptReadTable[idx](); /* Call 1st handler */ if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx]) { IoAccessCurrentAddress = addr + 1; pInterceptReadTable[idx+1](); /* Call 2nd handler */ } /* Check if we completely read from a bus-error region */ if (nBusErrorAccesses == 2) { M68000_BusError(addr, BUS_ERROR_READ); return -1; } val = IoMem_ReadWord(addr); LOG_TRACE(TRACE_IOMEM_RD, "IO read.w $%06x = $%04x\n", addr, val); return val; }
/** * Handle word read access from IO memory. */ uae_u32 IoMem_wget(uaecptr addr) { Uint32 idx; Uint16 val; if ((addr & IO_SEG_MASK) >= IO_SIZE) { /* invalid memory addressing --> bus error */ M68000_BusError(addr, BUS_ERROR_READ); return -1; } IoAccessBaseAddress = addr; /* Store for exception frame */ nIoMemAccessSize = SIZE_WORD; nBusErrorAccesses = 0; idx = addr & IO_SEG_MASK; IoAccessCurrentAddress = addr; pInterceptReadTable[idx](); /* Call 1st handler */ if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx]) { IoAccessCurrentAddress = addr + 1; pInterceptReadTable[idx+1](); /* Call 2nd handler */ } /* Check if we completely read from a bus-error region */ if (nBusErrorAccesses == 2) { M68000_BusError(addr, BUS_ERROR_READ); return -1; } val = IoMem_ReadWord(addr); LOG_TRACE(TRACE_IOMEM_RD, "IO read.w $%06x = $%04x\n", addr, val); return val; }
/** * Mix DMA sound sample with the normal PSG sound samples. */ void DmaSnd_GenerateSamples(int nMixBufIdx, int nSamplesToGenerate) { double FreqRatio; int i; int nBufIdx; Sint8 *pFrameStart; if (ConfigureParams.System.nMachineType == MACHINE_FALCON && (IoMem_ReadWord(0xff8932) & 0x6000) == 0x2000) { DmaSnd_GenerateDspSamples(nMixBufIdx, nSamplesToGenerate); return; } if (!(nDmaSoundControl & DMASNDCTRL_PLAY)) return; pFrameStart = (Sint8 *)&STRam[nFrameStartAddr]; FreqRatio = DmaSnd_DetectSampleRate() / (double)nAudioFrequency; if (ConfigureParams.System.nMachineType == MACHINE_FALCON && (nDmaSoundMode & DMASNDMODE_16BITSTEREO)) { /* Stereo 16-bit */ FreqRatio *= 4.0; for (i = 0; i < nSamplesToGenerate; i++) { nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE; MixBuffer[nBufIdx][0] = ((int)MixBuffer[nBufIdx][0] + (int)(*(Sint16*)&pFrameStart[((int)FrameCounter)&~1])) / 2; MixBuffer[nBufIdx][1] = ((int)MixBuffer[nBufIdx][1] + (int)(*(Sint16*)&pFrameStart[(((int)FrameCounter)&~1)+2])) / 2; FrameCounter += FreqRatio; if (DmaSnd_CheckForEndOfFrame(FrameCounter)) break; } } else if (nDmaSoundMode & DMASNDMODE_MONO) /* 8-bit stereo or mono? */ { /* Mono 8-bit */ for (i = 0; i < nSamplesToGenerate; i++) { nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE; MixBuffer[nBufIdx][0] = MixBuffer[nBufIdx][1] = ((int)MixBuffer[nBufIdx][0] + (((int)pFrameStart[(int)FrameCounter]) << 8)) / 2; FrameCounter += FreqRatio; if (DmaSnd_CheckForEndOfFrame(FrameCounter)) break; } } else { /* Stereo 8-bit */ FreqRatio *= 2.0; for (i = 0; i < nSamplesToGenerate; i++) { nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE; MixBuffer[nBufIdx][0] = ((int)MixBuffer[nBufIdx][0] + (((int)pFrameStart[((int)FrameCounter)&~1]) << 8)) / 2; MixBuffer[nBufIdx][1] = ((int)MixBuffer[nBufIdx][1] + (((int)pFrameStart[(((int)FrameCounter)&~1)+1]) << 8)) / 2; FrameCounter += FreqRatio; if (DmaSnd_CheckForEndOfFrame(FrameCounter)) break; } } }