|
|
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.6 ! root 11: const char PSG_rcsid[] = "Hatari $Id: psg.c,v 1.10 2006/02/08 22:49:27 eerot 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"
1.1.1.5 root 16: #include "joy.h"
1.1.1.4 root 17: #include "m68000.h"
1.1 root 18: #include "memorySnapShot.h"
19: #include "sound.h"
1.1.1.4 root 20: #include "printer.h" /* because Printer I/O goes through PSG Register 15 */
1.1.1.3 root 21: #include "psg.h"
22:
1.1 root 23:
1.1.1.4 root 24: Uint8 PSGRegisterSelect; /* 0xff8800 (read/write) */
25: Uint8 PSGRegisters[16]; /* Register in PSG, see PSG_REG_xxxx */
26:
27: static BOOL bLastWriteToIOB; /* boolean flag: did the last write to the PSG go to IOB? */
1.1 root 28:
29:
30: /*-----------------------------------------------------------------------*/
31: /*
32: Reset variables used in PSG
33: */
34: void PSG_Reset(void)
35: {
1.1.1.4 root 36: PSGRegisterSelect = 0;
37: memset(PSGRegisters, 0, sizeof(PSGRegisters));
38: bLastWriteToIOB = FALSE;
1.1 root 39: }
40:
1.1.1.2 root 41:
42: /*-----------------------------------------------------------------------*/
1.1 root 43: /*
1.1.1.4 root 44: Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
1.1 root 45: */
46: void PSG_MemorySnapShot_Capture(BOOL bSave)
47: {
1.1.1.4 root 48: /* Save/Restore details */
49: MemorySnapShot_Store(&PSGRegisterSelect, sizeof(PSGRegisterSelect));
50: MemorySnapShot_Store(PSGRegisters, sizeof(PSGRegisters));
51: MemorySnapShot_Store(&bLastWriteToIOB, sizeof(bLastWriteToIOB));
1.1 root 52: }
53:
1.1.1.2 root 54:
55: /*-----------------------------------------------------------------------*/
1.1 root 56: /*
1.1.1.4 root 57: Write byte to 0xff88000, this is used as a selector for when we read/write
58: to address 0xff8802
1.1 root 59: */
1.1.1.4 root 60: void PSG_SelectRegister_WriteByte(void)
1.1 root 61: {
1.1.1.6 ! root 62: M68000_WaitState(4);
1.1.1.4 root 63:
1.1.1.6 ! root 64: PSGRegisterSelect = IoMem[0xff8800] & 0x0f; /* Store register to select (value in bits 0-3) */
1.1 root 65: }
66:
1.1.1.2 root 67:
68: /*-----------------------------------------------------------------------*/
1.1 root 69: /*
1.1.1.5 root 70: Read byte from 0xff8800, returns PSG data
1.1 root 71: */
1.1.1.4 root 72: void PSG_SelectRegister_ReadByte(void)
1.1 root 73: {
1.1.1.6 ! root 74: M68000_WaitState(4);
! 75:
1.1.1.5 root 76: if (PSGRegisterSelect == 14)
77: {
78: /* Second parallel port joystick uses centronics strobe bit as fire button: */
79: if (ConfigureParams.Joysticks.Joy[JOYID_PARPORT2].nJoystickMode != JOYSTICK_DISABLED)
80: {
81: if (Joy_GetStickData(JOYID_PARPORT2) & 0x80)
82: PSGRegisters[14] &= ~32;
83: else
84: PSGRegisters[14] |= 32;
85: }
86: }
87: else if (PSGRegisterSelect == 15)
88: {
89: /* PSG register 15 is parallel port data register - used by parallel port joysticks: */
90: if (ConfigureParams.Joysticks.Joy[JOYID_PARPORT1].nJoystickMode != JOYSTICK_DISABLED)
91: {
92: PSGRegisters[15] &= 0x0f;
93: PSGRegisters[15] |= ~Joy_GetStickData(JOYID_PARPORT1) << 4;
94: }
95: if (ConfigureParams.Joysticks.Joy[JOYID_PARPORT2].nJoystickMode != JOYSTICK_DISABLED)
96: {
97: PSGRegisters[15] &= 0xf0;
98: PSGRegisters[15] |= ~Joy_GetStickData(JOYID_PARPORT2) & 0x0f;
99: }
100: }
101:
1.1.1.4 root 102: /* Read data last selected by register */
103: IoMem[0xff8800] = PSGRegisters[PSGRegisterSelect];
1.1 root 104: }
105:
1.1.1.2 root 106:
107: /*-----------------------------------------------------------------------*/
1.1 root 108: /*
1.1.1.4 root 109: Write byte to 0xff8802, stores according to PSG select register (write 0xff8800)
110: */
111: void PSG_DataRegister_WriteByte(void)
112: {
1.1.1.6 ! root 113: M68000_WaitState(4);
! 114:
1.1.1.4 root 115: Sound_Update(); /* Create samples up until this point with current values */
116: PSGRegisters[PSGRegisterSelect] = IoMem[0xff8802]; /* Write value to PSGRegisters[] */
117:
118: switch (PSGRegisterSelect)
119: {
120:
121: /* Check registers 8,9 and 10 which are 'amplitude' for each channel and
122: * store if wrote to (to check for sample playback) */
123: case PSG_REG_CHANNEL_A_AMP:
124: bWriteChannelAAmp = TRUE;
125: break;
126: case PSG_REG_CHANNEL_B_AMP:
127: bWriteChannelBAmp = TRUE;
128: break;
129: case PSG_REG_CHANNEL_C_AMP:
130: bWriteChannelCAmp = TRUE;
131: break;
132:
133: case PSG_REG_ENV_SHAPE: /* Whenever 'write' to register 13, cause envelope to reset */
134: bEnvelopeFreqFlag = TRUE;
135: bWriteEnvelopeFreq = TRUE;
136: break;
137:
138: /*
139: * FIXME: This is only a prelimary dirty hack!
140: * Port B (Printer port) - writing here needs to be dispatched to the printer
141: * STROBE (Port A bit5) does a short LOW and back to HIGH when the char is valid
142: * To print you need to write the character byte to IOB and you need to toggle STROBE
143: * (like EmuTOS does)....therefor we print when STROBE gets low and last write access to
144: * the PSG was to IOB
145: */
146: case PSG_REG_IO_PORTA:
147: /* Printer dispatching only when printing is activated */
148: if (ConfigureParams.Printer.bEnablePrinting)
149: {
150: /* Is STROBE low and did the last write go to IOB? */
151: if ((PSGRegisters[PSG_REG_IO_PORTA]&32)==0 && bLastWriteToIOB)
152: {
153: /* Seems like we want to print something... */
154: Printer_TransferByteTo((unsigned char) PSGRegisters[PSG_REG_IO_PORTB]);
155: }
156: }
157: break;
158: }
159:
160: /* Remember if we wrote to IO Port B */
161: bLastWriteToIOB = (PSGRegisterSelect == PSG_REG_IO_PORTB);
1.1 root 162: }
163:
1.1.1.2 root 164:
165: /*-----------------------------------------------------------------------*/
1.1 root 166: /*
167: Read byte from 0xff8802, returns 0xff
168: */
1.1.1.4 root 169: void PSG_DataRegister_ReadByte(void)
1.1 root 170: {
1.1.1.6 ! root 171: M68000_WaitState(4);
1.1.1.4 root 172:
1.1.1.6 ! root 173: IoMem[0xff8802] = 0xff;
1.1 root 174: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.