|
|
1.1 root 1: /* 1.1.1.4 ! root 2: Hatari - psg.c 1.1 root 3: 1.1.1.4 ! root 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. 1.1.1.3 root 6: 1.1.1.4 ! root 7: Programmable Sound Generator (YM-2149) - PSG 1.1.1.3 root 8: 1.1.1.4 ! root 9: Also used for the printer (centronics) port emulation (PSG Port B, Register 15) 1.1 root 10: */ 1.1.1.4 ! root 11: char PSG_rcsid[] = "Hatari $Id: psg.c,v 1.7 2005/01/18 23:33:24 thothy Exp $"; 1.1 root 12: 13: #include "main.h" 1.1.1.3 root 14: #include "configuration.h" 1.1.1.4 ! root 15: #include "ioMem.h" ! 16: #include "m68000.h" 1.1 root 17: #include "memorySnapShot.h" 18: #include "sound.h" 1.1.1.4 ! root 19: #include "printer.h" /* because Printer I/O goes through PSG Register 15 */ 1.1.1.3 root 20: #include "psg.h" 21: 1.1 root 22: 1.1.1.4 ! root 23: Uint8 PSGRegisterSelect; /* 0xff8800 (read/write) */ ! 24: Uint8 PSGRegisters[16]; /* Register in PSG, see PSG_REG_xxxx */ ! 25: ! 26: static BOOL bLastWriteToIOB; /* boolean flag: did the last write to the PSG go to IOB? */ 1.1 root 27: 28: 29: /*-----------------------------------------------------------------------*/ 30: /* 31: Reset variables used in PSG 32: */ 33: void PSG_Reset(void) 34: { 1.1.1.4 ! root 35: PSGRegisterSelect = 0; ! 36: memset(PSGRegisters, 0, sizeof(PSGRegisters)); ! 37: bLastWriteToIOB = FALSE; 1.1 root 38: } 39: 1.1.1.2 root 40: 41: /*-----------------------------------------------------------------------*/ 1.1 root 42: /* 1.1.1.4 ! root 43: Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type) 1.1 root 44: */ 45: void PSG_MemorySnapShot_Capture(BOOL bSave) 46: { 1.1.1.4 ! root 47: /* Save/Restore details */ ! 48: MemorySnapShot_Store(&PSGRegisterSelect, sizeof(PSGRegisterSelect)); ! 49: MemorySnapShot_Store(PSGRegisters, sizeof(PSGRegisters)); ! 50: MemorySnapShot_Store(&bLastWriteToIOB, sizeof(bLastWriteToIOB)); 1.1 root 51: } 52: 1.1.1.2 root 53: 54: /*-----------------------------------------------------------------------*/ 1.1 root 55: /* 1.1.1.4 ! root 56: Write byte to 0xff88000, this is used as a selector for when we read/write ! 57: to address 0xff8802 1.1 root 58: */ 1.1.1.4 ! root 59: void PSG_SelectRegister_WriteByte(void) 1.1 root 60: { 1.1.1.4 ! root 61: PSGRegisterSelect = IoMem[0xff8800] & 0x0f; /* Store register to select (value in bits 0-3) */ ! 62: ! 63: M68000_WaitState(); 1.1 root 64: } 65: 1.1.1.2 root 66: 67: /*-----------------------------------------------------------------------*/ 1.1 root 68: /* 69: Read byte from 0xff8800, returns to PSG data 70: */ 1.1.1.4 ! root 71: void PSG_SelectRegister_ReadByte(void) 1.1 root 72: { 1.1.1.4 ! root 73: /* Read data last selected by register */ ! 74: IoMem[0xff8800] = PSGRegisters[PSGRegisterSelect]; ! 75: ! 76: M68000_WaitState(); 1.1 root 77: } 78: 1.1.1.2 root 79: 80: /*-----------------------------------------------------------------------*/ 1.1 root 81: /* 1.1.1.4 ! root 82: Write byte to 0xff8802, stores according to PSG select register (write 0xff8800) ! 83: */ ! 84: void PSG_DataRegister_WriteByte(void) ! 85: { ! 86: Sound_Update(); /* Create samples up until this point with current values */ ! 87: PSGRegisters[PSGRegisterSelect] = IoMem[0xff8802]; /* Write value to PSGRegisters[] */ ! 88: ! 89: switch (PSGRegisterSelect) ! 90: { ! 91: ! 92: /* Check registers 8,9 and 10 which are 'amplitude' for each channel and ! 93: * store if wrote to (to check for sample playback) */ ! 94: case PSG_REG_CHANNEL_A_AMP: ! 95: bWriteChannelAAmp = TRUE; ! 96: break; ! 97: case PSG_REG_CHANNEL_B_AMP: ! 98: bWriteChannelBAmp = TRUE; ! 99: break; ! 100: case PSG_REG_CHANNEL_C_AMP: ! 101: bWriteChannelCAmp = TRUE; ! 102: break; ! 103: ! 104: case PSG_REG_ENV_SHAPE: /* Whenever 'write' to register 13, cause envelope to reset */ ! 105: bEnvelopeFreqFlag = TRUE; ! 106: bWriteEnvelopeFreq = TRUE; ! 107: break; ! 108: ! 109: /* ! 110: * FIXME: This is only a prelimary dirty hack! ! 111: * Port B (Printer port) - writing here needs to be dispatched to the printer ! 112: * STROBE (Port A bit5) does a short LOW and back to HIGH when the char is valid ! 113: * To print you need to write the character byte to IOB and you need to toggle STROBE ! 114: * (like EmuTOS does)....therefor we print when STROBE gets low and last write access to ! 115: * the PSG was to IOB ! 116: */ ! 117: case PSG_REG_IO_PORTA: ! 118: /* Printer dispatching only when printing is activated */ ! 119: if (ConfigureParams.Printer.bEnablePrinting) ! 120: { ! 121: /* Is STROBE low and did the last write go to IOB? */ ! 122: if ((PSGRegisters[PSG_REG_IO_PORTA]&32)==0 && bLastWriteToIOB) ! 123: { ! 124: /* Seems like we want to print something... */ ! 125: Printer_TransferByteTo((unsigned char) PSGRegisters[PSG_REG_IO_PORTB]); ! 126: } ! 127: } ! 128: break; ! 129: } ! 130: ! 131: /* Remember if we wrote to IO Port B */ ! 132: bLastWriteToIOB = (PSGRegisterSelect == PSG_REG_IO_PORTB); ! 133: ! 134: M68000_WaitState(); 1.1 root 135: } 136: 1.1.1.2 root 137: 138: /*-----------------------------------------------------------------------*/ 1.1 root 139: /* 140: Read byte from 0xff8802, returns 0xff 141: */ 1.1.1.4 ! root 142: void PSG_DataRegister_ReadByte(void) 1.1 root 143: { 1.1.1.4 ! root 144: IoMem[0xff8802] = 0xff; ! 145: ! 146: M68000_WaitState(); 1.1 root 147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.