|
|
| version 1.1.1.1, 2003/10/16 17:58:49 | version 1.5, 2004/02/13 08:01:12 |
|---|---|
| Line 1 | Line 1 |
| #include <windows.h> | #include "compiler.h" |
| #include "common.h" | |
| #if defined(SUPPORT_ROMEO) | |
| #include "romeo.h" | #include "romeo.h" |
| #include "juliet.h" | #include "juliet.h" |
| Line 7 | Line 8 |
| enum { | enum { |
| ROMEO_AVAIL = 0x01, | ROMEO_AVAIL = 0x01, |
| ROMEO_YMF288 = 0x02, // 必ず存在する筈? | ROMEO_YMF288 = 0x02, |
| ROMEO_YM2151 = 0x04 | ROMEO_YM2151 = 0x04 |
| }; | }; |
| typedef struct { | typedef struct { |
| HMODULE mod; | HMODULE mod; |
| PCIFINDDEV finddev; | ULONG (WINAPI * finddev)(ULONG ven, ULONG dev, ULONG index); |
| PCICFGREAD32 read32; | ULONG (WINAPI * read32)(ULONG pciaddr, ULONG regaddr); |
| PCIMEMWR8 out8; | void (WINAPI * out8)(ULONG addr, UCHAR param); |
| PCIMEMWR16 out16; | void (WINAPI * out16)(ULONG addr, USHORT param); |
| PCIMEMWR32 out32; | void (WINAPI * out32)(ULONG addr, ULONG param); |
| PCIMEMRD8 in8; | UCHAR (WINAPI * in8)(ULONG addr); |
| PCIMEMRD16 in16; | USHORT (WINAPI * in16)(ULONG addr); |
| PCIMEMRD32 in32; | ULONG (WINAPI * in32)(ULONG addr); |
| ULONG addr; | ULONG addr; |
| ULONG irq; | ULONG irq; |
| ULONG avail; | ULONG avail; |
| UINT8 algo[8]; | |
| UINT8 ttl[8*4]; | |
| UINT8 psgmix; | |
| } _ROMEO; | } _ROMEO; |
| #define ROMEO_TPTR(member) (int)&(((_ROMEO *)NULL)->member) | static const UINT8 opmask[] = {0x08,0x08,0x08,0x08,0x0c,0x0e,0x0e,0x0f}; |
| typedef struct { | typedef struct { |
| char *symbol; | const char *symbol; |
| int addr; | UINT addr; |
| } DLLPROCESS; | } DLLPROC; |
| static const DLLPROC dllproc[] = { | |
| {FN_PCIFINDDEV, offsetof(_ROMEO, finddev)}, | |
| {FN_PCICFGREAD32, offsetof(_ROMEO, read32)}, | |
| {FN_PCIMEMWR8, offsetof(_ROMEO, out8)}, | |
| {FN_PCIMEMWR16, offsetof(_ROMEO, out16)}, | |
| {FN_PCIMEMWR32, offsetof(_ROMEO, out32)}, | |
| {FN_PCIMEMRD8, offsetof(_ROMEO, in8)}, | |
| {FN_PCIMEMRD16, offsetof(_ROMEO, in16)}, | |
| {FN_PCIMEMRD32, offsetof(_ROMEO, in32)}}; | |
| static _ROMEO romeo = {NULL}; | |
| static const DLLPROCESS dllproc[] = { | |
| {FN_PCIFINDDEV, ROMEO_TPTR(finddev)}, | |
| {FN_PCICFGREAD32, ROMEO_TPTR(read32)}, | |
| {FN_PCIMEMWR8, ROMEO_TPTR(out8)}, | |
| {FN_PCIMEMWR16, ROMEO_TPTR(out16)}, | |
| {FN_PCIMEMWR32, ROMEO_TPTR(out32)}, | |
| {FN_PCIMEMRD8, ROMEO_TPTR(in8)}, | |
| {FN_PCIMEMRD16, ROMEO_TPTR(in16)}, | |
| {FN_PCIMEMRD32, ROMEO_TPTR(in32)}}; | |
| static _ROMEO romeo = {NULL}; | // pciFindPciDevice使うと、OS起動後一発目に見つけられないことが多いので、 |
| // 自前で検索する(矢野さん方式) | |
| #define PCIBUSDEVFUNC(b, d, f) (((b) << 8) | ((d) << 3) | (f)) | |
| #define DEVVEND(v, d) ((ULONG)((v) | ((d) << 16))) | |
| static ULONG searchRomeo(void) { | |
| UINT bus; | |
| UINT dev; | |
| UINT func; | |
| ULONG addr; | |
| ULONG dev_vend; | |
| for (bus=0; bus<0x100; bus++) { | |
| for (dev=0; dev<0x20; dev++) { | |
| for (func=0; func<0x08; func++) { | |
| addr = PCIBUSDEVFUNC(bus, dev, func); | |
| dev_vend = romeo.read32(addr, 0x0000); | |
| if ((dev_vend == DEVVEND(ROMEO_VENDORID, ROMEO_DEVICEID)) || | |
| (dev_vend == DEVVEND(ROMEO_VENDORID, ROMEO_DEVICEID2))) { | |
| return(addr); | |
| } | |
| } | |
| } | |
| } | |
| return((ULONG)0xffffffff); | |
| } | |
| BOOL juliet_load(void) { | |
| int i; | BOOL juliet_initialize(void) { |
| const DLLPROCESS *dp; | |
| BOOL r = SUCCESS; | |
| juliet_unload(); | HMODULE mod; |
| const DLLPROC *d; | |
| const DLLPROC *dterm; | |
| long proc; | |
| ULONG pciaddr; | |
| romeo.mod = LoadLibrary(PCIDEBUG_DLL); | juliet_deinitialize(); |
| if (romeo.mod == NULL) { | |
| return(FAILURE); | mod = LoadLibrary(PCIDEBUG_DLL); |
| if (mod == NULL) { | |
| goto jini_err1; | |
| } | } |
| for (i=0, dp=dllproc; i<sizeof(dllproc)/sizeof(DLLPROCESS); i++, dp++) { | romeo.mod = mod; |
| FARPROC proc; | d = dllproc; |
| proc = GetProcAddress(romeo.mod, dp->symbol); | dterm = d + sizeof(dllproc)/sizeof(DLLPROC); |
| if (proc == NULL) { | while(d < dterm) { |
| r = FAILURE; | proc = (long)GetProcAddress(mod, d->symbol); |
| break; | if (proc == (long)NULL) { |
| MessageBox(NULL, "0", "?", MB_OK); | |
| goto jini_err2; | |
| } | } |
| *(DWORD *)(((BYTE *)&romeo) + (dp->addr)) = (DWORD)proc; | *(long *)(((BYTE *)&romeo) + (d->addr)) = proc; |
| d++; | |
| } | } |
| if (r) { | |
| juliet_unload(); | pciaddr = searchRomeo(); |
| if (pciaddr == (ULONG)0xffffffff) { | |
| goto jini_err2; | |
| } | } |
| return(r); | romeo.addr = romeo.read32(pciaddr, ROMEO_BASEADDRESS1); |
| } | romeo.irq = romeo.read32(pciaddr, ROMEO_PCIINTERRUPT) & 0xff; |
| if (!romeo.addr) { | |
| goto jini_err2; | |
| } | |
| romeo.avail = ROMEO_AVAIL | ROMEO_YMF288; | |
| juliet_YMF288Reset(); | |
| TRACEOUT(("ROMEO enable")); | |
| return(SUCCESS); | |
| jini_err2: | |
| juliet_deinitialize(); | |
| jini_err1: | |
| return(FAILURE); | |
| } | |
| void juliet_unload(void) { | void juliet_deinitialize(void) { |
| if (romeo.mod) { | if (romeo.mod) { |
| FreeLibrary(romeo.mod); | FreeLibrary(romeo.mod); |
| } | } |
| ZeroMemory(&romeo, sizeof(romeo)); | ZeroMemory(&romeo, sizeof(romeo)); |
| FillMemory(romeo.ttl, 8*4, 0x7f); | |
| romeo.psgmix = 0x3f; | |
| } | } |
| // ---- | // ---- YMF288部 |
| ULONG juliet_prepare(void) { | |
| ULONG r; | static void YMF288A(UINT8 addr, UINT8 data) { |
| ULONG pciaddr; | |
| if (romeo.mod == NULL) { | while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { |
| return(FAILURE); | Sleep(0); |
| } | } |
| romeo.out8(romeo.addr + ROMEO_YMF288ADDR1, addr); | |
| r = romeo.finddev(ROMEO_VENDORID, ROMEO_DEVICEID, 0); | while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { |
| if (r & 0xff) { | Sleep(0); |
| r = romeo.finddev(ROMEO_VENDORID, ROMEO_DEVICEID2, 0); | |
| } | } |
| pciaddr = r >> 16; | romeo.out8(romeo.addr + ROMEO_YMF288DATA1, data); |
| r &= 0xff; | |
| if (!r) { | |
| romeo.addr = romeo.read32(pciaddr, ROMEO_BASEADDRESS1); | |
| romeo.irq = romeo.read32(pciaddr, ROMEO_PCIINTERRUPT) & 0xff; | |
| if (romeo.addr) { | |
| romeo.avail = ROMEO_AVAIL | ROMEO_YMF288; | |
| juliet_YM2151Reset(); | |
| juliet_YMF288Reset(); | |
| } | |
| } | |
| return(r); | |
| } | } |
| static void YMF288B(UINT8 addr, UINT8 data) { | |
| // ---- YM2151部 | while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { |
| Sleep(0); | |
| void juliet_YM2151Reset(void) | |
| { | |
| BYTE flag; | |
| if (romeo.avail & ROMEO_AVAIL) { | |
| romeo.out32(romeo.addr + ROMEO_YM2151CTRL, 0x00); | |
| Sleep(10); | |
| flag = romeo.in8(romeo.addr + ROMEO_YM2151DATA) + 1; | |
| romeo.out32(romeo.addr + ROMEO_YM2151CTRL, 0x80); | |
| Sleep(10); | |
| flag |= romeo.in8(romeo.addr + ROMEO_YM2151DATA); | |
| if (!flag) { | |
| romeo.avail |= ROMEO_YM2151; | |
| } | |
| } | } |
| romeo.out8(romeo.addr + ROMEO_YMF288ADDR2, addr); | |
| while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { | |
| Sleep(0); | |
| } | |
| romeo.out8(romeo.addr + ROMEO_YMF288DATA2, data); | |
| } | } |
| int juliet_YM2151IsEnable(void) | static void setvolume(UINT8 ch, int vol) { |
| { | |
| return (( romeo.avail&ROMEO_YM2151 )?TRUE:FALSE); | |
| } | |
| int juliet_YM2151IsBusy(void) | void (*send)(UINT8 addr, UINT8 data); |
| { | UINT8 mask; |
| UINT8 *pttl; | |
| int ttl; | |
| return ((!( romeo.avail&ROMEO_YM2151 ))|| ( ( romeo.in8(romeo.addr + ROMEO_CMDQUEUE)&0x0f )!=0x0f )); | send = (ch & 4)?YMF288B:YMF288A; |
| } | mask = opmask[romeo.algo[ch & 7] & 7]; |
| pttl = romeo.ttl + ((ch & 4) << 2); | |
| void juliet_YM2151W(BYTE reg, BYTE data) | ch = 0x40 + (ch & 3); |
| { | do { |
| if ( romeo.avail&ROMEO_YM2151) { | if (mask & 1) { |
| romeo.out8(romeo.addr + ROMEO_YM2151ADDR, reg); | ttl = pttl[ch & 0x0f] & 0x7f; |
| while ( (romeo.in8(romeo.addr + ROMEO_CMDQUEUE)&0x0f)!=0x0f ) { | ttl -= vol; |
| Sleep(0); | if (ttl < 0) { |
| ttl = 0; | |
| } | |
| else if (ttl > 0x7f) { | |
| ttl = 0x7f; | |
| } | |
| send(ch, (UINT8)ttl); | |
| } | } |
| romeo.out8(romeo.addr + ROMEO_YM2151DATA, data); | ch += 4; |
| } | mask >>= 1; |
| } while(mask); | |
| } | } |
| // ---- YMF288部 | |
| void juliet_YMF288Reset(void) { | void juliet_YMF288Reset(void) { |
| if (romeo.avail & ROMEO_YMF288) { | if (romeo.avail & ROMEO_YMF288) { |
| Line 174 void juliet_YMF288Reset(void) { | Line 211 void juliet_YMF288Reset(void) { |
| } | } |
| } | } |
| int juliet_YM288IsEnable(void) { | BOOL juliet_YMF288IsEnable(void) { |
| return(TRUE); | return((romeo.avail & ROMEO_YMF288) != 0); |
| } | } |
| int juliet_YM288IsBusy(void) { | BOOL juliet_YMF288IsBusy(void) { |
| return((!(romeo.avail&ROMEO_YMF288)) || | return((!(romeo.avail & ROMEO_YMF288)) || |
| ((romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) != 0)); | ((romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) != 0)); |
| } | } |
| void juliet_YMF288A(BYTE addr, BYTE data) { | void juliet_YMF288A(UINT8 addr, UINT8 data) { |
| if (romeo.avail & ROMEO_YMF288) { | if (romeo.avail & ROMEO_YMF288) { |
| while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { | if (addr == 0x07) { // psg mix |
| Sleep(0); | romeo.psgmix = data; |
| } | } |
| romeo.out8(romeo.addr + ROMEO_YMF288ADDR1, addr); | else if ((addr & 0xf0) == 0x40) { // ttl |
| while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { | romeo.ttl[addr & 0x0f] = data; |
| Sleep(0); | |
| } | } |
| romeo.out8(romeo.addr + ROMEO_YMF288DATA1, data); | else if ((addr & 0xfc) == 0xb0) { // algorithm |
| { | romeo.algo[addr & 3] = data; |
| char buf[128]; | |
| wsprintf(buf, "A-%02x %02x\n", addr, data); | |
| OutputDebugString(buf); | |
| } | } |
| YMF288A(addr, data); | |
| } | } |
| } | } |
| void juliet_YMF288B(BYTE addr, BYTE data) { | void juliet_YMF288B(UINT8 addr, UINT8 data) { |
| if (romeo.avail & ROMEO_YMF288) { | if (romeo.avail & ROMEO_YMF288) { |
| while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { | if ((addr & 0xf0) == 0x40) { // ttl |
| Sleep(0); | romeo.ttl[0x10 + (addr & 0x0f)] = data; |
| } | |
| else if ((addr & 0xfc) == 0xb0) { // algorithm | |
| romeo.algo[4 + (addr & 3)] = data; | |
| } | } |
| romeo.out8(romeo.addr + ROMEO_YMF288ADDR2, addr); | YMF288B(addr, data); |
| while(romeo.in8(romeo.addr + ROMEO_YMF288ADDR1) & 0x80) { | } |
| Sleep(0); | } |
| } | |
| romeo.out8(romeo.addr + ROMEO_YMF288DATA2, data); | void juliet_YMF288Enable(BOOL enable) { |
| { | |
| char buf[128]; | UINT8 ch; |
| wsprintf(buf, "B-%02x %02x\n", addr, data); | int vol; |
| OutputDebugString(buf); | |
| if (romeo.avail & ROMEO_YMF288) { | |
| YMF288A(0x07, (enable)?romeo.psgmix:0x3f); | |
| vol = (enable)?0:-127; | |
| for (ch=0; ch<3; ch++) { | |
| setvolume(ch+0, vol); | |
| setvolume(ch+4, vol); | |
| } | } |
| } | } |
| } | } |
| #endif | |