original xkeropi-20101107

This commit is contained in:
hissorii committed 2013-07-16 06:46:56 -07:00
commit d92ab3d7cb
156 files changed
+100405

No files matched your search

+98
View File
@@ -0,0 +1,98 @@
XCOMM $Id: Imakefile,v 1.4 2008/11/08 02:25:48 nonaka Exp $
#include "config.tmpl"
XCOMM GTK+
XCOMM for 1.2.x
XCOMM GTK_CONFIG?= gtk-config
XCOMM for 2.x
GTK_CONFIG?= pkg-config gtk+-2.0
GTK_INCLUDE= `$(GTK_CONFIG) --cflags`
GTK_LIB= `$(GTK_CONFIG) --libs`
XCOMM SDL 1.2
SDL_CONFIG?= sdl-config
SDL_INCLUDE= `$(SDL_CONFIG) --cflags`
SDL_LIB= `$(SDL_CONFIG) --libs`
NASM?= nasm
NASMFLAGS= -i ./x68k -i ./x11
NASMOBJFLAGS?= -f elf
#if defined(NO_SOUND)
EXTRA_DEFINES+= -DNOSOUND
#endif
#if defined(NO_MERCURY)
EXTRA_DEFINES+= -DNO_MERCURY
NASMFLAGS+= -DNO_MERCURY
#endif
SYS_LIBRARIES= -lm
EXTRA_INCLUDES= -I./x11 -I./x68k -I./fmgen -I./win32api \
$(GTK_INCLUDE) $(SDL_INCLUDE)
CXXEXTRA_INCLUDES= $(EXTRA_INCLUDES)
CXXEXTRA_DEFINES= $(EXTRA_DEFINES)
CXXDEBUGFLAGS= $(CDEBUGFLAGS)
LOCAL_LIBRARIES= $(XLIB) $(GTK_LIB) $(SDL_LIB)
#define PassCDebugFlags
CPUOBJS= x68k/d68k.o
CPUASMOBJS= x68k/68kem.o
X68KOBJS= \
x68k/adpcm.o x68k/bg.o x68k/crtc.o x68k/dmac.o x68k/fdc.o \
x68k/fdd.o x68k/disk_d88.o x68k/disk_dim.o x68k/disk_xdf.o \
x68k/gvram.o x68k/ioc.o x68k/irqh.o x68k/mem_wrap.o x68k/mercury.o \
x68k/mfp.o x68k/palette.o x68k/midi.o x68k/pia.o x68k/rtc.o \
x68k/sasi.o x68k/scc.o x68k/scsi.o x68k/sram.o x68k/sysport.o \
x68k/tvram.o \
x68k/cpu_glue.o
X68KASMOBJS= x68k/bga.o x68k/memory.o x68k/memory_glue.o
FMGENOBJS= \
fmgen/fmgen.o fmgen/fmg_wrap.o fmgen/file.o fmgen/fmtimer.o \
fmgen/opm.o fmgen/opna.o fmgen/psg.o
X11OBJS= \
x11/joystick.o x11/juliet.o x11/keyboard.o x11/mouse.o x11/prop.o \
x11/status.o x11/timer.o \
x11/dswin.o x11/windraw.o x11/winui.o \
x11/about.o
X11CXXOBJS= x11/winx68k.o
X11ASMOBJS= x11/haveunit.o
WIN32APIOBJS= win32api/dosio.o win32api/fake.o win32api/peace.o
AOBJS= $(CPUASMOBJS) $(X68KASMOBJS) $(X11ASMOBJS)
COBJS= $(X68KOBJS) $(X11OBJS) $(WIN32APIOBJS) $(CPUOBJS)
CXXOBJS= $(FMGENOBJS) $(X11CXXOBJS)
OBJS= $(COBJS) $(CXXOBJS) $(AOBJS)
ASRCS= $(AOBJS:.o=.asm)
CSRCS= $(COBJS:.o=.c)
CXXSRCS= $(CXXOBJS:.o=.cpp)
SRCS= $(CSRCS) $(CXXSRCS)
ALLSRCS= $(CSRCS) $(CXXSRCS) $(ASRCS)
.SUFFIXES: .asm .c .cpp
.c.o:
$(CC) -o $@ $(CFLAGS) $(_NOOP_) -c $*.c
.cpp.o:
$(CXX) -o $@ $(CXXFLAGS) $(_NOOP_) -c $*.cpp
.asm.o:
$(NASM) $(NASMFLAGS) $(NASMOBJFLAGS) $<
ComplexCplusplusProgramTarget(xkeropi)
cleandir distclean::
-$(RM) .depend
$(RM) $(OBJS)
+117
View File
@@ -0,0 +1,117 @@
xkeropi - エックスけろぴー (WinX68k for X)
0. xkeropi って何?
けんじょさん (http://retropc.net/kenjo/) が作成された SHARP X68000
エミュレータ WinX68k (通称けろぴー)を UNIX/X11 環境で動作する様に
移植した - ただし物凄く適当に - ソフトウェアです。
1. 環境
1.1. ソフトウェア
コンパイルには以下のソフトウェアが必要です。
・gcc (4.1.3 で動作確認をしています)
・nasm (2.03.01 で動作確認をしています)
・GTK+ 2.x
・SDL 1.2.x
1.2. 動作環境
以下の環境が必須です。
・Intel i386 互換 CPU (ただし、動作周波数 1GHz 位は必要)
・15bpp もしくは 16bpp の TrueColor/DirectColor で動作する X サーバ
1.3. 開発環境
開発環境は以下の通りです。
・NetBSD/i386
・GTK+ 2.14.4
・SDL 1.2.13
2. コンパイル&インストール方法
2.1. コンパイル
1) 必要があれば config.tmpl を編集
2) xmkmf -a
3) make
(必要があれば su 等で root になってください)
4) make install
2.2. config.tmpl で指定可能な内容
NO_SOUND : サウンド出力を無効化します。
このオプションを指定した場合には SDL は必要無い筈です。
NO_MERCURY : 「まーきゅりーゆにっと」を無効化します。
無効化すると多少動作が速くなるかもしれません。
2.3. インストール
1) BIOS の ROM イメージ、フォント ROM イメージを $(HOME)/.keropi 配下に
置いてください。その際、ファイル名は全て全て小文字にしてください。
BIOS ROM イメージは実機から取得するなり RetroPC Network さん
(http://retropc.net/) から辿れる X68000 LIBRARY から取得して
ください。
フォント ROM イメージは実機から取得してください。また、WinX68k を
フォント ROM 無しで起動した際に生成される cgrom.tmp も使用可能です。
3. 実行
コマンドラインから以下の様に入力してください。
シェルによっては rehash 等のコマンドをインストール後に実行する必要がある
かもしれません。
$ xkeropi
4. 操作
マウスの真ん中ボタンで X <-> x68k のマウス切り替えが可能です。
5. 備考
・初期設定では音が鳴らない様になっています。音を鳴らしたい場合には
 プログラム起動後に設定ダイアログでサンプリングレートを設定してください。
6. 問題点
・画面描画処理は動作が怪しいです。
・マウス処理も動作が怪しい様です。
・ステータスバーは未実装です。
・MIDI は未サポートです。
他、山程あるので書けません。
7. 謝辞
感謝する気持ちを忘れずに。
8. 連絡先
本ソフトウェアに関する問い合わせは以下のメールアドレスにお願いします。
NONAKA Kimihiro (埜中公博) / [email protected]
また、ソフトウェアのバージョンアップ等の情報は以下の URL から取得できます。
http://www.asahi-net.or.jp/~aw9k-nnk/keropi/
--
$Id: README.ja,v 1.5 2008/11/17 12:13:11 nonaka Exp $
+33
View File
@@ -0,0 +1,33 @@
XCOMM $Id: config.tmpl,v 1.3 2008/11/08 01:16:30 nonaka Exp $
XCOMM
XCOMM disable sound
XCOMM
#undef NO_SOUND
XCOMM
XCOMM disable mercury unit
XCOMM
#undef NO_MERCURY
XCOMM
XCOMM for Opt.
XCOMM
XCOMM CDEBUGFLAGS= -O3
XCOMM CDEBUGFLAGS+= -funroll-loops
XCOMM CDEBUGFLAGS+= -fomit-frame-pointer
XCOMM CDEBUGFLAGS+= -ffast-math
XCOMM CDEBUGFLAGS+= -march=pentium-m
XCOMM CDEBUGFLAGS+= -msse -mfpmath=sse
XCOMM
XCOMM for DEBUG
XCOMM
XCOMM CDEBUGFLAGS= -O0
XCOMM CDEBUGFLAGS+= -g
XCOMM CDEBUGFLAGS+= -W -Wall -Wuninitialized
XCOMM CDEBUGFLAGS+= -Wunused
XCOMM CDEBUGFLAGS+= -Werror
XCOMM CDEBUGFLAGS+= -DINLINE=
XCOMM CDEBUGFLAGS+= -DUSE_GAS
+160
View File
@@ -0,0 +1,160 @@
===================================================================
===== けろぴー(WinX68k)ソースコードドキュメント =====
===== (c) 2000,01 Kenjo =====
===================================================================
---------------
1. これは
---------------
 X68000エミュレータ「けろぴー」(旧「WinX68k」)のソースコードに
ついてのドキュメントです。
---------------
2. ファイル構成
---------------
 Microsoft Visual C++ 6.0 + NASMW で作成されています。
 ディレクトリは以下のような構造になっています(ヘッダファイルは省
略)。
--+-- Makefile VC++用Makeファイル
|
+--win32 Windows側のファイル群
| |
| +- about.c Aboutダイアログ
| +- common.c エラーダイアログなど
| +- cdaspi.c ASPIによるCD-ROMアクセス
| +- cdctrl.c IOCTRLによるCD-ROMアクセス
| +- cdrom.c CD-ROM(SCSI IOCS フック部)
| +- dsound.c DirectSound
| +- fileio.c ファイルアクセス
| +- joystick.c ジョイスティック入力
| +- keyboard.c キーボード入力
| +- keyconf.c キーコンフィグダイアログ
| +- mkcgrom.c CGROM作成ルーチン
| +- mouse.c マウス入力
| +- prop.c 設定用プロパティシート
| +- status.c ステータスバー表示
| +- timer.c タイマー
| +- windraw.c DirectDrawによる表示ルーチン
| +- winui.c メニューなどのUI関連
| +- winx68k.c メイン
| +- winx68k.rc リソースファイル
| +- adpcm.bmp リソース用画像データなど
| +- opm.bmp 〃
| +- nekolgc.bmp 〃
| +- motorola.bmp 〃
| +- keropi.bmp 〃
| +- keropi.ico 〃
| |
| +- msfiles Microsoftから提供のヘッダ/ライブラリ
| |
| +- msfiles.txt このディレクトリ内のファイルの入手元説明
|
+--x68k X68kの仮想デバイス群
| |
| +- 68kem.asm MPUコア(Make68kで自動生成+修正)
| +- comptab.asm ↑で使われるジャンプテーブル
| +- adpcm.c ADPCM
| +- bg.c BG/スプライト
| +- bg.x86 ↑用のアセンブラインクルードファイル
| +- crtc.c CRTC
| +- dmac.c DMAC
| +- fdc.c FDC
| +- fdd.c FDドライブ
| +- gvram.c グラフィックVRAM
| +- ioc.c I/Oコントローラ
| +- irqh.c IRQハンドラ
| +- memory.asm メモリアクセスルーチン
| +- memory.c メモリアクセス デバッグルーチン
| +- mercury.c ま~きゅり~ゆにっと
| +- mfp.c MFP
| +- midi.c MIDIボード
| +- opm.c OPM
| +- palette.c パレット
| +- pia.c 8255(ジョイスティック用)
| +- rtc.c RTC
| +- sasi.c SASI
| +- scc.c SCC(マウス用)
| +- scsi.c SCSIボード/BIOS(SPCへのI/Oはダミー)
| +- sram.c SRAM
| +- sysport.c システムポート
| +- tvram.c テキストVRAM
| +- windrv.c yamamaさんのWindrv.sys用デバイス
|
+-- release オブジェクトファイルが格納されるディレクトリ
---------------
3. コンパイル
---------------
 けろぴーをコンパイルするには、VC++とNASMWに加え、DirectX SDKが必要で
す。
 これらが正常にインストールされたマシンでDOS窓を開き、VC++とNASMWにパ
スが通った状態で、Makefile のあるディレクトリに移動し、
nmake
で実行ファイルが作成されます。
---------------
4. 2次使用、配布条件など
---------------
 商利用しない限りにおいて、一部のファイルを除き、改変、パクりなどは自由
です。パクって作ったソフトに関してもソースコード公開の義務はありません。
連絡も不要です(でも、使ったよ~と云ってもらえると嬉しいです(笑))。
 上記の条件から外れるのは、
1. MPUコア
Mike Coates 氏と Darren Olafson 氏の著作物です。流用する際は、両氏
へ連絡し、使用許可を貰って下さい。
Mike Coates氏連絡先 : [email protected]
Darren Olafson氏連絡先 : [email protected]
2. WINDRV.C
yamama氏の著作物です。流用する際は、yamama氏へ連絡し、使用許可を貰っ
て下さい。
yamama氏連絡先 : [email protected]
 それから、OPM.Cについては、多少変数名・関数は変わっていますが、基本的に
は Jarek Burczynski氏のコードをベースにしていますので、その点ご留意いただ
ければ幸いです。
 このコード自体の配布を目的とする場合は、アーカイブの中身は変更せずに、
ワンセットで配布して下さいね。
 著作権に関しては放棄しません(国内じゃしたくてもできないけど)。が、
まぁ好きに使って下さい(笑)。
---------------
5. 最後に
---------------
 汚いっす。見苦しいっす。プログラム下手糞っす。利用価値は無いっす。それ
でもいいよ、って方はご自由にお使いください(汗。
 一番分かりづらいのは「windraw.c」周りでしょうか……。
 描画の要はほぼ全てここに集まっていますが、フラグ立てまくりで既に私にも
訳が分かりません(ぉぃ。気が向いたら整理&ドキュメント作成でもしましょう
か……。
-----
de けんじょ
[email protected]
[email protected]
[EOF]
+15
View File
@@ -0,0 +1,15 @@
#ifndef incl_diag_h
#define incl_diag_h
#define LOG0(m) void (0)
#define LOG1(m,a) void (0)
#define LOG2(m,a,b) void (0)
#define LOG3(m,a,b,c) void (0)
#define LOG4(m,a,b,c,d) void (0)
#define LOG5(m,a,b,c,d,e) void (0)
#define LOG6(m,a,b,c,d,e,f) void (0)
#define LOG7(m,a,b,c,d,e,f,g) void (0)
#define LOG8(m,a,b,c,d,e,f,g,h) void (0)
#define LOG9(m,a,b,c,d,e,f,g,h,i) void (0)
#endif // incl_diag_h
+198
View File
@@ -0,0 +1,198 @@
// $fmgen-Id: file.cpp,v 1.6 1999/12/28 11:14:05 cisc Exp $
#include "common.h"
#include "headers.h"
#include "file.h"
// ---------------------------------------------------------------------------
// 構築/消滅
// ---------------------------------------------------------------------------
FileIO::FileIO()
{
flags = 0;
}
FileIO::FileIO(const char* filename, uint flg)
{
flags = 0;
Open(filename, flg);
}
FileIO::~FileIO()
{
Close();
}
// ---------------------------------------------------------------------------
// ファイルを開く
// ---------------------------------------------------------------------------
bool FileIO::Open(const char* filename, uint flg)
{
Close();
strncpy(path, filename, MAX_PATH);
DWORD access = (flg & readonly ? 0 : GENERIC_WRITE) | GENERIC_READ;
DWORD share = (flg & readonly) ? FILE_SHARE_READ : 0;
DWORD creation = flg & create ? CREATE_ALWAYS : OPEN_EXISTING;
hfile = CreateFile(filename, access, share, 0, creation, 0, 0);
flags = (flg & readonly) | (hfile == INVALID_HANDLE_VALUE ? 0 : open);
if (!(flags & open))
{
switch (GetLastError())
{
case ERROR_FILE_NOT_FOUND: error = file_not_found; break;
case ERROR_SHARING_VIOLATION: error = sharing_violation; break;
default: error = unknown; break;
}
}
SetLogicalOrigin(0);
return !!(flags & open);
}
// ---------------------------------------------------------------------------
// ファイルがない場合は作成
// ---------------------------------------------------------------------------
bool FileIO::CreateNew(const char* filename)
{
Close();
strncpy(path, filename, MAX_PATH);
DWORD access = GENERIC_WRITE | GENERIC_READ;
DWORD share = 0;
DWORD creation = CREATE_NEW;
hfile = CreateFile(filename, access, share, 0, creation, 0, 0);
flags = (hfile == INVALID_HANDLE_VALUE ? 0 : open);
SetLogicalOrigin(0);
return !!(flags & open);
}
// ---------------------------------------------------------------------------
// ファイルを作り直す
// ---------------------------------------------------------------------------
bool FileIO::Reopen(uint flg)
{
if (!(flags & open)) return false;
if ((flags & readonly) && (flg & create)) return false;
if (flags & readonly) flg |= readonly;
Close();
DWORD access = (flg & readonly ? 0 : GENERIC_WRITE) | GENERIC_READ;
DWORD share = flg & readonly ? FILE_SHARE_READ : 0;
DWORD creation = flg & create ? CREATE_ALWAYS : OPEN_EXISTING;
hfile = CreateFile(path, access, share, 0, creation, 0, 0);
flags = (flg & readonly) | (hfile == INVALID_HANDLE_VALUE ? 0 : open);
SetLogicalOrigin(0);
return !!(flags & open);
}
// ---------------------------------------------------------------------------
// ファイルを閉じる
// ---------------------------------------------------------------------------
void FileIO::Close()
{
if (GetFlags() & open)
{
CloseHandle(hfile);
flags = 0;
}
}
// ---------------------------------------------------------------------------
// ファイル殻の読み出し
// ---------------------------------------------------------------------------
int32 FileIO::Read(void* dest, int32 size)
{
if (!(GetFlags() & open))
return -1;
DWORD readsize;
if (!ReadFile(hfile, dest, size, &readsize, 0))
return -1;
return readsize;
}
// ---------------------------------------------------------------------------
// ファイルへの書き出し
// ---------------------------------------------------------------------------
int32 FileIO::Write(const void* dest, int32 size)
{
if (!(GetFlags() & open) || (GetFlags() & readonly))
return -1;
DWORD writtensize;
if (!WriteFile(hfile, dest, size, &writtensize, 0))
return -1;
return writtensize;
}
// ---------------------------------------------------------------------------
// ファイルをシーク
// ---------------------------------------------------------------------------
bool FileIO::Seek(int32 pos, SeekMethod method)
{
if (!(GetFlags() & open))
return false;
DWORD wmethod;
switch (method)
{
case begin:
wmethod = FILE_BEGIN; pos += lorigin;
break;
case current:
wmethod = FILE_CURRENT;
break;
case end:
wmethod = FILE_END;
break;
default:
return false;
}
return 0xffffffff != SetFilePointer(hfile, pos, 0, wmethod);
}
// ---------------------------------------------------------------------------
// ファイルの位置を得る
// ---------------------------------------------------------------------------
int32 FileIO::Tellp()
{
if (!(GetFlags() & open))
return 0;
return SetFilePointer(hfile, 0, 0, FILE_CURRENT) - lorigin;
}
// ---------------------------------------------------------------------------
// 現在の位置をファイルの終端とする
// ---------------------------------------------------------------------------
bool FileIO::SetEndOfFile()
{
if (!(GetFlags() & open))
return false;
return ::SetEndOfFile(hfile) != 0;
}
+64
View File
@@ -0,0 +1,64 @@
// $fmgen-Id: file.h,v 1.6 1999/11/26 10:14:09 cisc Exp $
#if !defined(win32_file_h)
#define win32_file_h
#include "fmgen_types.h"
// ---------------------------------------------------------------------------
class FileIO
{
public:
enum Flags
{
open = 0x000001,
readonly = 0x000002,
create = 0x000004,
};
enum SeekMethod
{
begin = 0, current = 1, end = 2,
};
enum Error
{
success = 0,
file_not_found,
sharing_violation,
unknown = -1
};
public:
FileIO();
FileIO(const char* filename, uint flg = 0);
virtual ~FileIO();
bool Open(const char* filename, uint flg = 0);
bool CreateNew(const char* filename);
bool Reopen(uint flg = 0);
void Close();
Error GetError() { return error; }
int32 Read(void* dest, int32 len);
int32 Write(const void* src, int32 len);
bool Seek(int32 fpos, SeekMethod method);
int32 Tellp();
bool SetEndOfFile();
uint GetFlags() { return flags; }
void SetLogicalOrigin(int32 origin) { lorigin = origin; }
private:
HANDLE hfile;
uint flags;
uint32 lorigin;
Error error;
char path[MAX_PATH];
FileIO(const FileIO&);
const FileIO& operator=(const FileIO&);
};
#endif //
+364
View File
@@ -0,0 +1,364 @@
// ciscタンノエロガゾウキボンヌを強引にけろぴーに繋ぐための
// extern "C" の入れ方がきちゃなくてステキ(ぉ
// readme.txtに従って、改変点:
// - opna.cppにYMF288用のクラス追加してます。OPNAそのまんまだけどね(ほんとは正しくないがまあいいや)
// - 多分他は弄ってないはず……
extern "C" {
#include "common.h"
#include "winx68k.h"
#include "dswin.h"
#include "prop.h"
#include "juliet.h"
#include "mfp.h"
#include "adpcm.h"
#include "mercury.h"
#include "fdc.h"
#include "fmg_wrap.h"
#include "opm.h"
#include "opna.h"
#define RMBUFSIZE (256*1024)
typedef struct {
unsigned int time;
int reg;
BYTE data;
} RMDATA;
};
static RMDATA RMData[RMBUFSIZE];
static int RMPtrW;
static int RMPtrR;
class MyOPM : public FM::OPM
{
public:
MyOPM();
virtual ~MyOPM() {}
void WriteIO(DWORD adr, BYTE data);
void Count2(DWORD clock);
private:
virtual void Intr(bool);
int CurReg;
DWORD CurCount;
};
MyOPM::MyOPM()
{
CurReg = 0;
}
void MyOPM::WriteIO(DWORD adr, BYTE data)
{
if( adr&1 ) {
if ( CurReg==0x1b ) {
::ADPCM_SetClock((data>>5)&4);
::FDC_SetForceReady((data>>6)&1);
}
SetReg((int)CurReg, (int)data);
if ( (juliet_YM2151IsEnable())&&(Config.SoundROMEO) ) {
int newptr = (RMPtrW+1)%RMBUFSIZE;
if ( newptr!=RMPtrR ) {
#if 0
RMData[RMPtrW].time = timeGetTime();
RMData[RMPtrW].reg = CurReg;
if ( CurReg==0x14 ) data &= 0xf3; // Int Enableはマスクする
RMData[RMPtrW].data = data;
RMPtrW = newptr;
}
#else
OPM_RomeoOut(Config.BufferSize*5);
}
RMData[RMPtrW].time = timeGetTime();
RMData[RMPtrW].reg = CurReg;
if ( CurReg==0x14 ) data &= 0xf3; // Int Enableはマスクする
RMData[RMPtrW].data = data;
RMPtrW = newptr;
#endif
}
} else {
CurReg = (int)data;
}
}
void MyOPM::Intr(bool f)
{
if ( f ) ::MFP_Int(12);
}
void MyOPM::Count2(DWORD clock)
{
CurCount += clock;
Count(CurCount/10);
CurCount %= 10;
}
static MyOPM* opm = NULL;
int OPM_Init(int clock, int rate)
{
juliet_load();
juliet_prepare();
RMPtrW = RMPtrR = 0;
memset(RMData, 0, sizeof(RMData));
opm = new MyOPM();
if ( !opm ) return FALSE;
if ( !opm->Init(clock, rate, TRUE) ) {
delete opm;
opm = NULL;
return FALSE;
}
return TRUE;
}
void OPM_Cleanup(void)
{
juliet_YM2151Reset();
juliet_unload();
delete opm;
opm = NULL;
}
void OPM_SetRate(int clock, int rate)
{
if ( opm ) opm->SetRate(clock, rate, TRUE);
}
void OPM_Reset(void)
{
RMPtrW = RMPtrR = 0;
memset(RMData, 0, sizeof(RMData));
if ( opm ) opm->Reset();
juliet_YM2151Reset();
}
BYTE FASTCALL OPM_Read(WORD adr)
{
BYTE ret = 0;
(void)adr;
if ( opm ) ret = opm->ReadStatus();
if ( (juliet_YM2151IsEnable())&&(Config.SoundROMEO) ) {
int newptr = (RMPtrW+1)%RMBUFSIZE;
ret = (ret&0x7f)|((newptr==RMPtrR)?0x80:0x00);
}
return ret;
}
void FASTCALL OPM_Write(DWORD adr, BYTE data)
{
if ( opm ) opm->WriteIO(adr, data);
}
void OPM_Update(short *buffer, int length)
{
if ( (!juliet_YM2151IsEnable())||(!Config.SoundROMEO) )
if ( opm ) opm->Mix((FM::Sample*)buffer, length);
}
void FASTCALL OPM_Timer(DWORD step)
{
if ( opm ) opm->Count2(step);
}
void OPM_SetVolume(BYTE vol)
{
int v = (vol)?((16-vol)*4):192; // このくらいかなぁ
if ( opm ) opm->SetVolume(-v);
}
void OPM_RomeoOut(unsigned int delay)
{
unsigned int t = timeGetTime();
if ( (juliet_YM2151IsEnable())&&(Config.SoundROMEO) ) {
while ( RMPtrW!=RMPtrR ) {
if ( (t-RMData[RMPtrR].time)>=delay ) {
juliet_YM2151W(RMData[RMPtrR].reg, RMData[RMPtrR].data);
RMPtrR = (RMPtrR+1)%RMBUFSIZE;
} else
break;
}
}
}
// ----------------------------------------------------------
// ---------------------------- YMF288 (満開版ま~きゅり~)
// ----------------------------------------------------------
// TODO : ROMEOの288を叩くの
class YMF288 : public FM::Y288
{
public:
YMF288();
virtual ~YMF288() {}
void WriteIO(DWORD adr, BYTE data);
BYTE ReadIO(DWORD adr);
void Count2(DWORD clock);
void SetInt(int f) { IntrFlag = f; };
private:
virtual void Intr(bool);
int CurReg[2];
DWORD CurCount;
int IntrFlag;
};
YMF288::YMF288()
{
CurReg[0] = 0;
CurReg[1] = 0;
IntrFlag = 0;
}
void YMF288::WriteIO(DWORD adr, BYTE data)
{
if( adr&1 ) {
SetReg(((adr&2)?(CurReg[1]+0x100):CurReg[0]), (int)data);
} else {
CurReg[(adr>>1)&1] = (int)data;
}
}
BYTE YMF288::ReadIO(DWORD adr)
{
BYTE ret = 0;
if ( adr&1 ) {
ret = GetReg(((adr&2)?(CurReg[1]+0x100):CurReg[0]));
} else {
ret = ((adr)?(ReadStatusEx()):(ReadStatus()));
}
return ret;
}
void YMF288::Intr(bool f)
{
if ( (f)&&(IntrFlag) ) ::Mcry_Int();
}
void YMF288::Count2(DWORD clock)
{
CurCount += clock;
Count(CurCount/10);
CurCount %= 10;
}
static YMF288* ymf288a = NULL;
static YMF288* ymf288b = NULL;
int M288_Init(int clock, int rate, const char* path)
{
ymf288a = new YMF288();
ymf288b = new YMF288();
if ( (!ymf288a)||(!ymf288b) ) {
M288_Cleanup();
return FALSE;
}
if ( (!ymf288a->Init(clock, rate, TRUE, path))||(!ymf288b->Init(clock, rate, TRUE, path)) ) {
M288_Cleanup();
return FALSE;
}
ymf288a->SetInt(1);
ymf288b->SetInt(0);
return TRUE;
}
void M288_Cleanup(void)
{
delete ymf288a;
delete ymf288b;
ymf288a = ymf288b = NULL;
}
void M288_SetRate(int clock, int rate)
{
if ( ymf288a ) ymf288a->SetRate(clock, rate, TRUE);
if ( ymf288b ) ymf288b->SetRate(clock, rate, TRUE);
}
void M288_Reset(void)
{
if ( ymf288a ) ymf288a->Reset();
if ( ymf288b ) ymf288b->Reset();
}
BYTE FASTCALL M288_Read(WORD adr)
{
if ( adr<=3 ) {
if ( ymf288a )
return ymf288a->ReadIO(adr);
else
return 0;
} else {
if ( ymf288b )
return ymf288b->ReadIO(adr&3);
else
return 0;
}
}
void FASTCALL M288_Write(DWORD adr, BYTE data)
{
if ( adr<=3 ) {
if ( ymf288a ) ymf288a->WriteIO(adr, data);
} else {
if ( ymf288b ) ymf288b->WriteIO(adr&3, data);
}
}
void M288_Update(short *buffer, int length)
{
if ( ymf288a ) ymf288a->Mix((FM::Sample*)buffer, length);
if ( ymf288b ) ymf288b->Mix((FM::Sample*)buffer, length);
}
void FASTCALL M288_Timer(DWORD step)
{
if ( ymf288a ) ymf288a->Count2(step);
if ( ymf288b ) ymf288b->Count2(step);
}
void M288_SetVolume(BYTE vol)
{
int v1 = (vol)?((16-vol)*4-24):192; // このくらいかなぁ
int v2 = (vol)?((16-vol)*4):192; // 少し小さめに
if ( ymf288a ) {
ymf288a->SetVolumeFM(-v1);
ymf288a->SetVolumePSG(-v2);
}
if ( ymf288b ) {
ymf288b->SetVolumeFM(-v1);
ymf288b->SetVolumePSG(-v2);
}
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef _win68_opm_fmgen
#define _win68_opm_fmgen
int OPM_Init(int clock, int rate);
void OPM_Cleanup(void);
void OPM_Reset(void);
void OPM_Update(short *buffer, int length);
void FASTCALL OPM_Write(DWORD r, BYTE v);
BYTE FASTCALL OPM_Read(WORD a);
void FASTCALL OPM_Timer(DWORD step);
void OPM_SetVolume(BYTE vol);
void OPM_SetRate(int clock, int rate);
void OPM_RomeoOut(unsigned int delay);
int M288_Init(int clock, int rate, const char* path);
void M288_Cleanup(void);
void M288_Reset(void);
void M288_Update(short *buffer, int length);
void FASTCALL M288_Write(DWORD r, BYTE v);
BYTE FASTCALL M288_Read(WORD a);
void FASTCALL M288_Timer(DWORD step);
void M288_SetVolume(BYTE vol);
void M288_SetRate(int clock, int rate);
void M288_RomeoOut(unsigned int delay);
#endif //_win68_opm_fmgen
+966
View File
@@ -0,0 +1,966 @@
// ---------------------------------------------------------------------------
// FM Sound Generator - Core Unit
// Copyright (C) cisc 1998, 2003.
// ---------------------------------------------------------------------------
// $fmgen-Id: fmgen.cpp,v 1.49 2003/09/02 14:51:04 cisc Exp $
// ---------------------------------------------------------------------------
// 参考:
// FM sound generator for M.A.M.E., written by Tatsuyuki Satoh.
//
// 謎:
// OPNB の CSM モード(仕様がよくわからない)
//
// 制限:
// ・AR!=31 で SSGEC を使うと波形が実際と異なる可能性あり
//
// 謝辞:
// Tatsuyuki Satoh さん(fm.c)
// Hiromitsu Shioya さん(ADPCM-A)
// DMP-SOFT. さん(OPNB)
// KAJA さん(test program)
// ほか掲示板等で様々なご助言,ご支援をお寄せいただいた皆様に
// ---------------------------------------------------------------------------
#include "headers.h"
#include "misc.h"
#include "fmgen.h"
#include "fmgeninl.h"
#define LOGNAME "fmgen"
// ---------------------------------------------------------------------------
#define FM_EG_BOTTOM 955
// ---------------------------------------------------------------------------
// Table/etc
//
namespace FM
{
const uint8 Operator::notetable[128] =
{
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11,
12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15,
16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19,
20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23,
24, 24, 24, 24, 24, 24, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27,
28, 28, 28, 28, 28, 28, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31,
};
const int8 Operator::dttable[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4,
4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, 16, 16, 16, 16,
2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10,
10, 12, 12, 14, 16, 16, 18, 20, 22, 24, 26, 28, 32, 32, 32, 32,
4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14,
16, 16, 18, 20, 22, 24, 26, 28, 32, 34, 38, 40, 44, 44, 44, 44,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, -4, -4, -4, -4,
-4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14,-16,-16,-16,-16,
-2, -2, -2, -2, -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10,
-10,-12,-12,-14,-16,-16,-18,-20,-22,-24,-26,-28,-32,-32,-32,-32,
-4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14,
-16,-16,-18,-20,-22,-24,-26,-28,-32,-34,-38,-40,-44,-44,-44,-44,
};
const int8 Operator::decaytable1[64][8] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1,
2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1,
2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 2, 2,
4, 2, 4, 2, 4, 2, 4, 2, 4, 4, 4, 2, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 4, 4,
8, 4, 8, 4, 8, 4, 8, 4, 8, 8, 8, 4, 8, 8, 8, 4,
16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,
};
const int Operator::decaytable2[16] =
{
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2047, 2047, 2047, 2047, 2047
};
const int8 Operator::attacktable[64][8] =
{
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1,
4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1,
4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4,
3, 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4,
3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3,
2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2,
1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0,
};
const int Operator::ssgenvtable[8][2][3][2] =
{
1, 1, 1, 1, 1, 1, // 08
0, 1, 1, 1, 1, 1, // 08 56~
0, 1, 2, 0, 2, 0, // 09
0, 1, 2, 0, 2, 0, // 09
1,-1, 0, 1, 1,-1, // 10
0, 1, 1,-1, 0, 1, // 10 60~
1,-1, 0, 0, 0, 0, // 11
0, 1, 0, 0, 0, 0, // 11 60~
2,-1, 2,-1, 2,-1, // 12
1,-1, 2,-1, 2,-1, // 12 56~
1,-1, 0, 0, 0, 0, // 13
1,-1, 0, 0, 0, 0, // 13
0, 1, 1,-1, 0, 1, // 14
1,-1, 0, 1, 1,-1, // 14 60~
0, 1, 2, 0, 2, 0, // 15
1,-1, 2, 0, 2, 0, // 15 60~
};
// fixed equasion-based tables
int pmtable[2][8][FM_LFOENTS];
uint amtable[2][4][FM_LFOENTS];
static bool tablemade = false;
}
namespace FM
{
// ---------------------------------------------------------------------------
// テーブル作成
//
void MakeLFOTable()
{
if (tablemade)
return;
tablemade = true;
int i;
static const double pms[2][8] =
{
{ 0, 1/360., 2/360., 3/360., 4/360., 6/360., 12/360., 24/360., }, // OPNA
// { 0, 1/240., 2/240., 4/240., 10/240., 20/240., 80/240., 140/240., }, // OPM
{ 0, 1/480., 2/480., 4/480., 10/480., 20/480., 80/480., 140/480., }, // OPM
// { 0, 1/960., 2/960., 4/960., 10/960., 20/960., 80/960., 140/960., }, // OPM
};
// 3 6, 12 30 60 240 420 / 720
// 1.000963
// lfofref[level * max * wave];
// pre = lfofref[level][pms * wave >> 8];
static const uint8 amt[2][4] =
{
{ 31, 6, 4, 3 }, // OPNA
{ 31, 2, 1, 0 }, // OPM
};
for (int type = 0; type < 2; type++)
{
for (i=0; i<8; i++)
{
double pmb = pms[type][i];
for (int j=0; j<FM_LFOENTS; j++)
{
//double v = pow(2.0, pmb * (2 * j - FM_LFOENTS+1) / (FM_LFOENTS-1));
double w = 0.6 * pmb * sin(2 * j * 3.14159265358979323846 / FM_LFOENTS) + 1;
// pmtable[type][i][j] = int(0x10000 * (v - 1));
// if (type == 0)
pmtable[type][i][j] = int(0x10000 * (w - 1));
// else
// pmtable[type][i][j] = int(0x10000 * (v - 1));
// printf("pmtable[%d][%d][%.2x] = %5d %7.5f %7.5f\n", type, i, j, pmtable[type][i][j], v, w);
}
}
for (i=0; i<4; i++)
{
for (int j=0; j<FM_LFOENTS; j++)
{
amtable[type][i][j] = (((j * 4) >> amt[type][i]) * 2) << 2;
}
}
}
}
// ---------------------------------------------------------------------------
// チップ内で共通な部分
//
Chip::Chip()
: ratio_(0), aml_(0), pml_(0), pmv_(0), optype_(typeN)
{
}
// クロック・サンプリングレート比に依存するテーブルを作成
void Chip::SetRatio(uint ratio)
{
if (ratio_ != ratio)
{
ratio_ = ratio;
MakeTable();
}
}
void Chip::MakeTable()
{
int h, l;
// PG Part
static const float dt2lv[4] = { 1.f, 1.414f, 1.581f, 1.732f };
for (h=0; h<4; h++)
{
assert(2 + FM_RATIOBITS - FM_PGBITS >= 0);
double rr = dt2lv[h] * double(ratio_) / (1 << (2 + FM_RATIOBITS - FM_PGBITS));
for (l=0; l<16; l++)
{
int mul = l ? l * 2 : 1;
multable_[h][l] = uint(mul * rr);
}
}
}
// ---------------------------------------------------------------------------
// Operator
//
bool FM::Operator::tablehasmade = false;
uint FM::Operator::sinetable[1024];
int32 FM::Operator::cltable[FM_CLENTS];
// 構築
FM::Operator::Operator()
: chip_(0)
{
if (!tablehasmade)
MakeTable();
// EG Part
ar_ = dr_ = sr_ = rr_ = key_scale_rate_ = 0;
ams_ = amtable[0][0];
mute_ = false;
keyon_ = false;
tl_out_ = false;
ssg_type_ = 0;
// PG Part
multiple_ = 0;
detune_ = 0;
detune2_ = 0;
// LFO
ms_ = 0;
// Reset();
}
// 初期化
void FM::Operator::Reset()
{
// EG part
tl_ = tl_latch_ = 127;
ShiftPhase(off);
eg_count_ = 0;
eg_curve_count_ = 0;
ssg_phase_ = 0;
// PG part
pg_count_ = 0;
// OP part
out_ = out2_ = 0;
param_changed_ = true;
PARAMCHANGE(0);
}
void Operator::MakeTable()
{
// 対数テーブルの作成
assert(FM_CLENTS >= 256);
int* p = cltable;
int i;
for (i=0; i<256; i++)
{
int v = int(floor(pow(2., 13. - i / 256.)));
v = (v + 2) & ~3;
*p++ = v;
*p++ = -v;
}
while (p < cltable + FM_CLENTS)
{
*p++ = p[-512] / 2;
}
// for (i=0; i<13*256; i++)
// printf("%4d, %d, %d\n", i, cltable[i*2], cltable[i*2+1]);
// サインテーブルの作成
double log2 = log(2.);
for (i=0; i<FM_OPSINENTS/2; i++)
{
double r = (i * 2 + 1) * FM_PI / FM_OPSINENTS;
double q = -256 * log(sin(r)) / log2;
uint s = (int) (floor(q + 0.5)) + 1;
// printf("%d, %d\n", s, cltable[s * 2] / 8);
sinetable[i] = s * 2 ;
sinetable[FM_OPSINENTS / 2 + i] = s * 2 + 1;
}
::FM::MakeLFOTable();
tablehasmade = true;
}
inline void FM::Operator::SetDPBN(uint dp, uint bn)
{
dp_ = dp, bn_ = bn; param_changed_ = true;
PARAMCHANGE(1);
}
// 準備
void Operator::Prepare()
{
if (param_changed_)
{
param_changed_ = false;
// PG Part
pg_diff_ = (dp_ + dttable[detune_ + bn_]) * chip_->GetMulValue(detune2_, multiple_);
pg_diff_lfo_ = pg_diff_ >> 11;
// EG Part
key_scale_rate_ = bn_ >> (3-ks_);
tl_out_ = mute_ ? 0x3ff : tl_ * 8;
switch (eg_phase_)
{
case attack:
SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0);
break;
case decay:
SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0);
eg_level_on_next_phase_ = sl_ * 8;
break;
case sustain:
SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0);
break;
case release:
SetEGRate(Min(63, rr_ + key_scale_rate_));
break;
case next:
case off:
break;
}
// SSG-EG
if (ssg_type_ && (eg_phase_ != release))
{
int m = ar_ >= ((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60);
assert(0 <= ssg_phase_ && ssg_phase_ <= 2);
const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_];
ssg_offset_ = table[0] * 0x200;
ssg_vector_ = table[1];
}
// LFO
ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0];
EGUpdate();
dbgopout_ = 0;
}
}
// envelop の eg_phase_ 変更
void Operator::ShiftPhase(EGPhase nextphase)
{
switch (nextphase)
{
case attack: // Attack Phase
tl_ = tl_latch_;
if (ssg_type_)
{
ssg_phase_ = ssg_phase_ + 1;
if (ssg_phase_ > 2)
ssg_phase_ = 1;
int m = ar_ >= ((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60);
assert(0 <= ssg_phase_ && ssg_phase_ <= 2);
const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_];
ssg_offset_ = table[0] * 0x200;
ssg_vector_ = table[1];
}
if ((ar_ + key_scale_rate_) < 62)
{
SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0);
eg_phase_ = attack;
break;
}
case decay: // Decay Phase
if (sl_)
{
eg_level_ = 0;
eg_level_on_next_phase_ = ssg_type_ ? Min(sl_ * 8, 0x200) : sl_ * 8;
SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0);
eg_phase_ = decay;
break;
}
case sustain: // Sustain Phase
eg_level_ = sl_ * 8;
eg_level_on_next_phase_ = ssg_type_ ? 0x200 : 0x400;
SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0);
eg_phase_ = sustain;
break;
case release: // Release Phase
if (ssg_type_)
{
eg_level_ = eg_level_ * ssg_vector_ + ssg_offset_;
ssg_vector_ = 1;
ssg_offset_ = 0;
}
if (eg_phase_ == attack || (eg_level_ < FM_EG_BOTTOM)) //0x400/* && eg_phase_ != off*/))
{
eg_level_on_next_phase_ = 0x400;
SetEGRate(Min(63, rr_ + key_scale_rate_));
eg_phase_ = release;
break;
}
case off: // off
default:
eg_level_ = FM_EG_BOTTOM;
eg_level_on_next_phase_ = FM_EG_BOTTOM;
EGUpdate();
SetEGRate(0);
eg_phase_ = off;
break;
}
}
// Block/F-Num
void Operator::SetFNum(uint f)
{
dp_ = (f & 2047) << ((f >> 11) & 7);
bn_ = notetable[(f >> 7) & 127];
param_changed_ = true;
PARAMCHANGE(2);
}
// 1サンプル合成
// ISample を envelop count (2π) に変換するシフト量
#define IS2EC_SHIFT ((20 + FM_PGBITS) - 13)
// 入力: s = 20+FM_PGBITS = 29
#define Sine(s) sinetable[((s) >> (20+FM_PGBITS-FM_OPSINBITS))&(FM_OPSINENTS-1)]
#define SINE(s) sinetable[(s) & (FM_OPSINENTS-1)]
inline FM::ISample Operator::LogToLin(uint a)
{
#if 1 // FM_CLENTS < 0xc00 // 400 for TL, 400 for ENV, 400 for LFO.
return (a < FM_CLENTS) ? cltable[a] : 0;
#else
return cltable[a];
#endif
}
inline void Operator::EGUpdate()
{
if (!ssg_type_)
{
eg_out_ = Min(tl_out_ + eg_level_, 0x3ff) << (1 + 2);
}
else
{
eg_out_ = Min(tl_out_ + eg_level_ * ssg_vector_ + ssg_offset_, 0x3ff) << (1 + 2);
}
}
inline void Operator::SetEGRate(uint rate)
{
eg_rate_ = rate;
eg_count_diff_ = decaytable2[rate / 4] * chip_->GetRatio();
}
// EG 計算
void FM::Operator::EGCalc()
{
eg_count_ = (2047 * 3) << FM_RATIOBITS; // ##この手抜きは再現性を低下させる
if (eg_phase_ == attack)
{
int c = attacktable[eg_rate_][eg_curve_count_ & 7];
if (c >= 0)
{
eg_level_ -= 1 + (eg_level_ >> c);
if (eg_level_ <= 0)
ShiftPhase(decay);
}
EGUpdate();
}
else
{
if (!ssg_type_)
{
eg_level_ += decaytable1[eg_rate_][eg_curve_count_ & 7];
if (eg_level_ >= eg_level_on_next_phase_)
ShiftPhase(EGPhase(eg_phase_+1));
EGUpdate();
}
else
{
eg_level_ += 4 * decaytable1[eg_rate_][eg_curve_count_ & 7];
if (eg_level_ >= eg_level_on_next_phase_)
{
EGUpdate();
switch (eg_phase_)
{
case decay:
ShiftPhase(sustain);
break;
case sustain:
ShiftPhase(attack);
break;
case release:
ShiftPhase(off);
break;
case next:
case attack:
case off:
break;
}
}
}
}
eg_curve_count_++;
}
inline void FM::Operator::EGStep()
{
eg_count_ -= eg_count_diff_;
// EG の変化は全スロットで同期しているという噂もある
if (eg_count_ <= 0)
EGCalc();
}
// PG 計算
// ret:2^(20+PGBITS) / cycle
inline uint32 FM::Operator::PGCalc()
{
uint32 ret = pg_count_;
pg_count_ += pg_diff_;
dbgpgout_ = ret;
return ret;
}
inline uint32 FM::Operator::PGCalcL()
{
uint32 ret = pg_count_;
pg_count_ += pg_diff_ + ((pg_diff_lfo_ * chip_->GetPMV()) >> 5);// & -(1 << (2+IS2EC_SHIFT)));
dbgpgout_ = ret;
return ret /* + pmv * pg_diff_;*/;
}
// OP 計算
// in: ISample (最大 8π)
inline FM::ISample FM::Operator::Calc(ISample in)
{
EGStep();
out2_ = out_;
int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS);
pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT));
out_ = LogToLin(eg_out_ + SINE(pgin));
dbgopout_ = out_;
return out_;
}
inline FM::ISample FM::Operator::CalcL(ISample in)
{
EGStep();
int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS);
pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT));
out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]);
dbgopout_ = out_;
return out_;
}
inline FM::ISample FM::Operator::CalcN(uint noise)
{
EGStep();
int lv = Max(0, 0x3ff - (tl_out_ + eg_level_)) << 1;
// noise & 1 ? lv : -lv と等価
noise = (noise & 1) - 1;
out_ = (lv + noise) ^ noise;
dbgopout_ = out_;
return out_;
}
// OP (FB) 計算
// Self Feedback の変調最大 = 4π
inline FM::ISample FM::Operator::CalcFB(uint fb)
{
EGStep();
ISample in = out_ + out2_;
out2_ = out_;
int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS);
if (fb < 31)
{
pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS);
}
out_ = LogToLin(eg_out_ + SINE(pgin));
dbgopout_ = out2_;
return out2_;
}
inline FM::ISample FM::Operator::CalcFBL(uint fb)
{
EGStep();
ISample in = out_ + out2_;
out2_ = out_;
int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS);
if (fb < 31)
{
pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS);
}
out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]);
dbgopout_ = out_;
return out_;
}
#undef Sine
// ---------------------------------------------------------------------------
// 4-op Channel
//
const uint8 Channel4::fbtable[8] = { 31, 7, 6, 5, 4, 3, 2, 1 };
int Channel4::kftable[64];
bool Channel4::tablehasmade = false;
Channel4::Channel4()
{
if (!tablehasmade)
MakeTable();
SetAlgorithm(0);
pms = pmtable[0][0];
}
void Channel4::MakeTable()
{
// 100/64 cent = 2^(i*100/64*1200)
for (int i=0; i<64; i++)
{
kftable[i] = int(0x10000 * pow(2., i / 768.) );
}
}
// リセット
void Channel4::Reset()
{
op[0].Reset();
op[1].Reset();
op[2].Reset();
op[3].Reset();
}
// Calc の用意
int Channel4::Prepare()
{
op[0].Prepare();
op[1].Prepare();
op[2].Prepare();
op[3].Prepare();
pms = pmtable[op[0].type_][op[0].ms_ & 7];
int key = (op[0].IsOn() | op[1].IsOn() | op[2].IsOn() | op[3].IsOn()) ? 1 : 0;
int lfo = op[0].ms_ & (op[0].amon_ | op[1].amon_ | op[2].amon_ | op[3].amon_ ? 0x37 : 7) ? 2 : 0;
return key | lfo;
}
// F-Number/BLOCK を設定
void Channel4::SetFNum(uint f)
{
for (int i=0; i<4; i++)
op[i].SetFNum(f);
}
// KC/KF を設定
void Channel4::SetKCKF(uint kc, uint kf)
{
static const uint kctable[16] =
{
5197, 5506, 5833, 6180, 6180, 6547, 6937, 7349,
7349, 7786, 8249, 8740, 8740, 9259, 9810, 10394,
};
int oct = 19 - ((kc >> 4) & 7);
//printf("%p", this);
uint kcv = kctable[kc & 0x0f];
kcv = (kcv + 2) / 4 * 4;
//printf(" %.4x", kcv);
uint dp = kcv * kftable[kf & 0x3f];
//printf(" %.4x %.4x %.8x", kcv, kftable[kf & 0x3f], dp >> oct);
dp >>= 16 + 3;
dp <<= 16 + 3;
dp >>= oct;
uint bn = (kc >> 2) & 31;
op[0].SetDPBN(dp, bn);
op[1].SetDPBN(dp, bn);
op[2].SetDPBN(dp, bn);
op[3].SetDPBN(dp, bn);
//printf(" %.8x\n", dp);
}
// キー制御
void Channel4::KeyControl(uint key)
{
if (key & 0x1) op[0].KeyOn(); else op[0].KeyOff();
if (key & 0x2) op[1].KeyOn(); else op[1].KeyOff();
if (key & 0x4) op[2].KeyOn(); else op[2].KeyOff();
if (key & 0x8) op[3].KeyOn(); else op[3].KeyOff();
}
// アルゴリズムを設定
void Channel4::SetAlgorithm(uint algo)
{
static const uint8 table1[8][6] =
{
{ 0, 1, 1, 2, 2, 3 }, { 1, 0, 0, 1, 1, 2 },
{ 1, 1, 1, 0, 0, 2 }, { 0, 1, 2, 1, 1, 2 },
{ 0, 1, 2, 2, 2, 1 }, { 0, 1, 0, 1, 0, 1 },
{ 0, 1, 2, 1, 2, 1 }, { 1, 0, 1, 0, 1, 0 },
};
in [0] = &buf[table1[algo][0]];
out[0] = &buf[table1[algo][1]];
in [1] = &buf[table1[algo][2]];
out[1] = &buf[table1[algo][3]];
in [2] = &buf[table1[algo][4]];
out[2] = &buf[table1[algo][5]];
op[0].ResetFB();
algo_ = algo;
}
// 合成
ISample Channel4::Calc()
{
int r = 0;
switch (algo_)
{
case 0:
op[2].Calc(op[1].Out());
op[1].Calc(op[0].Out());
r = op[3].Calc(op[2].Out());
op[0].CalcFB(fb);
break;
case 1:
op[2].Calc(op[0].Out() + op[1].Out());
op[1].Calc(0);
r = op[3].Calc(op[2].Out());
op[0].CalcFB(fb);
break;
case 2:
op[2].Calc(op[1].Out());
op[1].Calc(0);
r = op[3].Calc(op[0].Out() + op[2].Out());
op[0].CalcFB(fb);
break;
case 3:
op[2].Calc(0);
op[1].Calc(op[0].Out());
r = op[3].Calc(op[1].Out() + op[2].Out());
op[0].CalcFB(fb);
break;
case 4:
op[2].Calc(0);
r = op[1].Calc(op[0].Out());
r += op[3].Calc(op[2].Out());
op[0].CalcFB(fb);
break;
case 5:
r = op[2].Calc(op[0].Out());
r += op[1].Calc(op[0].Out());
r += op[3].Calc(op[0].Out());
op[0].CalcFB(fb);
break;
case 6:
r = op[2].Calc(0);
r += op[1].Calc(op[0].Out());
r += op[3].Calc(0);
op[0].CalcFB(fb);
break;
case 7:
r = op[2].Calc(0);
r += op[1].Calc(0);
r += op[3].Calc(0);
r += op[0].CalcFB(fb);
break;
}
return r;
}
// 合成
ISample Channel4::CalcL()
{
chip_->SetPMV(pms[chip_->GetPML()]);
int r = 0;
switch (algo_)
{
case 0:
op[2].CalcL(op[1].Out());
op[1].CalcL(op[0].Out());
r = op[3].CalcL(op[2].Out());
op[0].CalcFBL(fb);
break;
case 1:
op[2].CalcL(op[0].Out() + op[1].Out());
op[1].CalcL(0);
r = op[3].CalcL(op[2].Out());
op[0].CalcFBL(fb);
break;
case 2:
op[2].CalcL(op[1].Out());
op[1].CalcL(0);
r = op[3].CalcL(op[0].Out() + op[2].Out());
op[0].CalcFBL(fb);
break;
case 3:
op[2].CalcL(0);
op[1].CalcL(op[0].Out());
r = op[3].CalcL(op[1].Out() + op[2].Out());
op[0].CalcFBL(fb);
break;
case 4:
op[2].CalcL(0);
r = op[1].CalcL(op[0].Out());
r += op[3].CalcL(op[2].Out());
op[0].CalcFBL(fb);
break;
case 5:
r = op[2].CalcL(op[0].Out());
r += op[1].CalcL(op[0].Out());
r += op[3].CalcL(op[0].Out());
op[0].CalcFBL(fb);
break;
case 6:
r = op[2].CalcL(0);
r += op[1].CalcL(op[0].Out());
r += op[3].CalcL(0);
op[0].CalcFBL(fb);
break;
case 7:
r = op[2].CalcL(0);
r += op[1].CalcL(0);
r += op[3].CalcL(0);
r += op[0].CalcFBL(fb);
break;
}
return r;
}
// 合成
ISample Channel4::CalcN(uint noise)
{
buf[1] = buf[2] = buf[3] = 0;
buf[0] = op[0].out_; op[0].CalcFB(fb);
*out[0] += op[1].Calc(*in[0]);
*out[1] += op[2].Calc(*in[1]);
int o = op[3].out_;
op[3].CalcN(noise);
return *out[2] + o;
}
// 合成
ISample Channel4::CalcLN(uint noise)
{
chip_->SetPMV(pms[chip_->GetPML()]);
buf[1] = buf[2] = buf[3] = 0;
buf[0] = op[0].out_; op[0].CalcFBL(fb);
*out[0] += op[1].CalcL(*in[0]);
*out[1] += op[2].CalcL(*in[1]);
int o = op[3].out_;
op[3].CalcN(noise);
return *out[2] + o;
}
} // namespace FM
+267
View File
@@ -0,0 +1,267 @@
// ---------------------------------------------------------------------------
// FM Sound Generator
// Copyright (C) cisc 1998, 2001.
// ---------------------------------------------------------------------------
// $fmgen-Id: fmgen.h,v 1.37 2003/08/25 13:33:11 cisc Exp $
#ifndef FM_GEN_H
#define FM_GEN_H
#include "common.h"
#include "fmgen_types.h"
// ---------------------------------------------------------------------------
// 出力サンプルの型
//
#define FM_SAMPLETYPE int32 // int16 or int32
// ---------------------------------------------------------------------------
// 定数その1
// 静的テーブルのサイズ
#define FM_LFOBITS 8 // 変更不可
#define FM_TLBITS 7
// ---------------------------------------------------------------------------
#define FM_TLENTS (1 << FM_TLBITS)
#define FM_LFOENTS (1 << FM_LFOBITS)
#define FM_TLPOS (FM_TLENTS/4)
// サイン波の精度は 2^(1/256)
#define FM_CLENTS (0x1000 * 2) // sin + TL + LFO
// ---------------------------------------------------------------------------
namespace FM
{
// Types ----------------------------------------------------------------
typedef FM_SAMPLETYPE Sample;
typedef int32 ISample;
enum OpType { typeN=0, typeM=1 };
void StoreSample(ISample& dest, int data);
class Chip;
// Operator -------------------------------------------------------------
class Operator
{
public:
Operator();
void SetChip(Chip* chip) { chip_ = chip; }
static void MakeTimeTable(uint ratio);
ISample Calc(ISample in);
ISample CalcL(ISample in);
ISample CalcFB(uint fb);
ISample CalcFBL(uint fb);
ISample CalcN(uint noise);
void Prepare();
void KeyOn();
void KeyOff();
void Reset();
void ResetFB();
int IsOn();
void SetDT(uint dt);
void SetDT2(uint dt2);
void SetMULTI(uint multi);
void SetTL(uint tl, bool csm);
void SetKS(uint ks);
void SetAR(uint ar);
void SetDR(uint dr);
void SetSR(uint sr);
void SetRR(uint rr);
void SetSL(uint sl);
void SetSSGEC(uint ssgec);
void SetFNum(uint fnum);
void SetDPBN(uint dp, uint bn);
void SetMode(bool modulator);
void SetAMON(bool on);
void SetMS(uint ms);
void Mute(bool);
// static void SetAML(uint l);
// static void SetPML(uint l);
int Out() { return out_; }
int dbgGetIn2() { return in2_; }
void dbgStopPG() { pg_diff_ = 0; pg_diff_lfo_ = 0; }
private:
typedef uint32 Counter;
Chip* chip_;
ISample out_, out2_;
ISample in2_;
// Phase Generator ------------------------------------------------------
uint32 PGCalc();
uint32 PGCalcL();
uint dp_; // ΔP
uint detune_; // Detune
uint detune2_; // DT2
uint multiple_; // Multiple
uint32 pg_count_; // Phase 現在値
uint32 pg_diff_; // Phase 差分値
int32 pg_diff_lfo_; // Phase 差分値 >> x
// Envelop Generator ---------------------------------------------------
enum EGPhase { next, attack, decay, sustain, release, off };
void EGCalc();
void EGStep();
void ShiftPhase(EGPhase nextphase);
void SSGShiftPhase(int mode);
void SetEGRate(uint);
void EGUpdate();
int FBCalc(int fb);
ISample LogToLin(uint a);
OpType type_; // OP の種類 (M, N...)
uint bn_; // Block/Note
int eg_level_; // EG の出力値
int eg_level_on_next_phase_; // 次の eg_phase_ に移る値
int eg_count_; // EG の次の変移までの時間
int eg_count_diff_; // eg_count_ の差分
int eg_out_; // EG+TL を合わせた出力値
int tl_out_; // TL 分の出力値
// int pm_depth_; // PM depth
// int am_depth_; // AM depth
int eg_rate_;
int eg_curve_count_;
int ssg_offset_;
int ssg_vector_;
int ssg_phase_;
uint key_scale_rate_; // key scale rate
EGPhase eg_phase_;
uint* ams_;
uint ms_;
uint tl_; // Total Level (0-127)
uint tl_latch_; // Total Level Latch (for CSM mode)
uint ar_; // Attack Rate (0-63)
uint dr_; // Decay Rate (0-63)
uint sr_; // Sustain Rate (0-63)
uint sl_; // Sustain Level (0-127)
uint rr_; // Release Rate (0-63)
uint ks_; // Keyscale (0-3)
uint ssg_type_; // SSG-Type Envelop Control
bool keyon_;
bool amon_; // enable Amplitude Modulation
bool param_changed_; // パラメータが更新された
bool mute_;
// Tables ---------------------------------------------------------------
static Counter rate_table[16];
static uint32 multable[4][16];
static const uint8 notetable[128];
static const int8 dttable[256];
static const int8 decaytable1[64][8];
static const int decaytable2[16];
static const int8 attacktable[64][8];
static const int ssgenvtable[8][2][3][2];
static uint sinetable[1024];
static int32 cltable[FM_CLENTS];
static bool tablehasmade;
static void MakeTable();
// friends --------------------------------------------------------------
friend class Channel4;
friend void __stdcall FM_NextPhase(Operator* op);
public:
int dbgopout_;
int dbgpgout_;
static const int32* dbgGetClTable() { return cltable; }
static const uint* dbgGetSineTable() { return sinetable; }
};
// 4-op Channel ---------------------------------------------------------
class Channel4
{
public:
Channel4();
void SetChip(Chip* chip);
void SetType(OpType type);
ISample Calc();
ISample CalcL();
ISample CalcN(uint noise);
ISample CalcLN(uint noise);
void SetFNum(uint fnum);
void SetFB(uint fb);
void SetKCKF(uint kc, uint kf);
void SetAlgorithm(uint algo);
int Prepare();
void KeyControl(uint key);
void Reset();
void SetMS(uint ms);
void Mute(bool);
void Refresh();
void dbgStopPG() { for (int i=0; i<4; i++) op[i].dbgStopPG(); }
private:
static const uint8 fbtable[8];
uint fb;
int buf[4];
int* in[3]; // 各 OP の入力ポインタ
int* out[3]; // 各 OP の出力ポインタ
int* pms;
int algo_;
Chip* chip_;
static void MakeTable();
static bool tablehasmade;
static int kftable[64];
public:
Operator op[4];
};
// Chip resource
class Chip
{
public:
Chip();
void SetRatio(uint ratio);
void SetAML(uint l);
void SetPML(uint l);
void SetPMV(int pmv) { pmv_ = pmv; }
uint32 GetMulValue(uint dt2, uint mul) { return multable_[dt2][mul]; }
uint GetAML() { return aml_; }
uint GetPML() { return pml_; }
int GetPMV() { return pmv_; }
uint GetRatio() { return ratio_; }
private:
void MakeTable();
uint ratio_;
uint aml_;
uint pml_;
int pmv_;
OpType optype_;
uint32 multable_[4][16];
};
}
#endif // FM_GEN_H
+22
View File
@@ -0,0 +1,22 @@
#if !defined(win32_types_h)
#define win32_types_h
// 盖年墓房とか
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef signed char sint8;
typedef signed short sint16;
typedef signed int sint32;
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
#endif // win32_types_h
+268
View File
@@ -0,0 +1,268 @@
// ---------------------------------------------------------------------------
// FM Sound Generator
// Copyright (C) cisc 1998, 2003.
// ---------------------------------------------------------------------------
// $fmgen-Id: fmgeninl.h,v 1.26 2003/06/12 13:14:36 cisc Exp $
#ifndef FM_GEN_INL_H
#define FM_GEN_INL_H
// ---------------------------------------------------------------------------
// 定数その2
//
#define FM_PI 3.14159265358979323846
#define FM_SINEPRESIS 2 // EGとサイン波の精度の差 0(低)-2(高)
#define FM_OPSINBITS 10
#define FM_OPSINENTS (1 << FM_OPSINBITS)
#define FM_EGCBITS 18 // eg の count のシフト値
#define FM_LFOCBITS 14
#ifdef FM_TUNEBUILD
#define FM_PGBITS 2
#define FM_RATIOBITS 0
#else
#define FM_PGBITS 9
#define FM_RATIOBITS 7 // 8-12 くらいまで?
#endif
#define FM_EGBITS 16
//extern int paramcount[];
//#define PARAMCHANGE(i) paramcount[i]++;
#define PARAMCHANGE(i)
namespace FM
{
// ---------------------------------------------------------------------------
// Operator
//
// フィードバックバッファをクリア
inline void Operator::ResetFB()
{
out_ = out2_ = 0;
}
// キーオン
inline void Operator::KeyOn()
{
if (!keyon_)
{
keyon_ = true;
if (eg_phase_ == off || eg_phase_ == release)
{
ssg_phase_ = -1;
ShiftPhase(attack);
EGUpdate();
in2_ = out_ = out2_ = 0;
pg_count_ = 0;
}
}
}
// キーオフ
inline void Operator::KeyOff()
{
if (keyon_)
{
keyon_ = false;
ShiftPhase(release);
}
}
// オペレータは稼働中か?
inline int Operator::IsOn()
{
return eg_phase_ - off;
}
// Detune (0-7)
inline void Operator::SetDT(uint dt)
{
detune_ = dt * 0x20, param_changed_ = true;
PARAMCHANGE(4);
}
// DT2 (0-3)
inline void Operator::SetDT2(uint dt2)
{
detune2_ = dt2 & 3, param_changed_ = true;
PARAMCHANGE(5);
}
// Multiple (0-15)
inline void Operator::SetMULTI(uint mul)
{
multiple_ = mul, param_changed_ = true;
PARAMCHANGE(6);
}
// Total Level (0-127) (0.75dB step)
inline void Operator::SetTL(uint tl, bool csm)
{
if (!csm)
{
tl_ = tl, param_changed_ = true;
PARAMCHANGE(7);
}
tl_latch_ = tl;
}
// Attack Rate (0-63)
inline void Operator::SetAR(uint ar)
{
ar_ = ar;
param_changed_ = true;
PARAMCHANGE(8);
}
// Decay Rate (0-63)
inline void Operator::SetDR(uint dr)
{
dr_ = dr;
param_changed_ = true;
PARAMCHANGE(9);
}
// Sustain Rate (0-63)
inline void Operator::SetSR(uint sr)
{
sr_ = sr;
param_changed_ = true;
PARAMCHANGE(10);
}
// Sustain Level (0-127)
inline void Operator::SetSL(uint sl)
{
sl_ = sl;
param_changed_ = true;
PARAMCHANGE(11);
}
// Release Rate (0-63)
inline void Operator::SetRR(uint rr)
{
rr_ = rr;
param_changed_ = true;
PARAMCHANGE(12);
}
// Keyscale (0-3)
inline void Operator::SetKS(uint ks)
{
ks_ = ks;
param_changed_ = true;
PARAMCHANGE(13);
}
// SSG-type Envelop (0-15)
inline void Operator::SetSSGEC(uint ssgec)
{
if (ssgec & 8)
ssg_type_ = ssgec;
else
ssg_type_ = 0;
}
inline void Operator::SetAMON(bool amon)
{
amon_ = amon;
param_changed_ = true;
PARAMCHANGE(14);
}
inline void Operator::Mute(bool mute)
{
mute_ = mute;
param_changed_ = true;
PARAMCHANGE(15);
}
inline void Operator::SetMS(uint ms)
{
ms_ = ms;
param_changed_ = true;
PARAMCHANGE(16);
}
// ---------------------------------------------------------------------------
// 4-op Channel
// オペレータの種類 (LFO) を設定
inline void Channel4::SetType(OpType type)
{
for (int i=0; i<4; i++)
op[i].type_ = type;
}
// セルフ・フィードバックレートの設定 (0-7)
inline void Channel4::SetFB(uint feedback)
{
fb = fbtable[feedback];
}
// OPNA 系 LFO の設定
inline void Channel4::SetMS(uint ms)
{
op[0].SetMS(ms);
op[1].SetMS(ms);
op[2].SetMS(ms);
op[3].SetMS(ms);
}
// チャンネル・マスク
inline void Channel4::Mute(bool m)
{
for (int i=0; i<4; i++)
op[i].Mute(m);
}
// 内部パラメータを再計算
inline void Channel4::Refresh()
{
for (int i=0; i<4; i++)
op[i].param_changed_ = true;
PARAMCHANGE(3);
}
inline void Channel4::SetChip(Chip* chip)
{
chip_ = chip;
for (int i=0; i<4; i++)
op[i].SetChip(chip);
}
// ---------------------------------------------------------------------------
//
//
inline void StoreSample(Sample& dest, ISample data)
{
if (sizeof(Sample) == 2)
dest = (Sample) Limit(dest + data, 0x7fff, -0x8000);
else
dest += data;
}
// ---------------------------------------------------------------------------
// AM のレベルを設定
inline void Chip::SetAML(uint l)
{
aml_ = l & (FM_LFOENTS - 1);
}
// PM のレベルを設定
inline void Chip::SetPML(uint l)
{
pml_ = l & (FM_LFOENTS - 1);
}
}
#endif // FM_GEN_INL_H
+191
View File
@@ -0,0 +1,191 @@
// ---------------------------------------------------------------------------
// FM sound generator common timer module
// Copyright (C) cisc 1998, 2000.
// ---------------------------------------------------------------------------
// $fmgen-Id: fmtimer.cpp,v 1.1 2000/09/08 13:45:56 cisc Exp $
#include "common.h"
#include "fmgen_types.h"
#include "headers.h"
#include "fmtimer.h"
using namespace FM;
// ---------------------------------------------------------------------------
// タイマー制御
//
void Timer::SetTimerControl(uint data)
{
uint tmp = regtc ^ data;
regtc = uint8(data);
if (data & 0x10)
ResetStatus(1);
if (data & 0x20)
ResetStatus(2);
if (tmp & 0x01)
timera_count = (data & 1) ? timera : 0;
if (tmp & 0x02)
timerb_count = (data & 2) ? timerb : 0;
}
#if 1
// ---------------------------------------------------------------------------
// タイマーA 周期設定
//
void Timer::SetTimerA(uint addr, uint data)
{
uint tmp;
regta[addr & 1] = uint8(data);
tmp = (regta[0] << 2) + (regta[1] & 3);
timera = (1024-tmp) * timer_step;
// LOG2("Timer A = %d %d us\n", tmp, timera >> 16);
}
// ---------------------------------------------------------------------------
// タイマーB 周期設定
//
void Timer::SetTimerB(uint data)
{
timerb = (256-data) * timer_step;
// LOG2("Timer B = %d %d us\n", data, timerb >> 12);
}
// ---------------------------------------------------------------------------
// タイマー時間処理
//
bool Timer::Count(int32 us)
{
bool event = false;
if (timera_count)
{
timera_count -= us << 16;
if (timera_count <= 0)
{
event = true;
TimerA();
while (timera_count <= 0)
timera_count += timera;
if (regtc & 4)
SetStatus(1);
}
}
if (timerb_count)
{
timerb_count -= us << 12;
if (timerb_count <= 0)
{
event = true;
while (timerb_count <= 0)
timerb_count += timerb;
if (regtc & 8)
SetStatus(2);
}
}
return event;
}
// ---------------------------------------------------------------------------
// 次にタイマーが発生するまでの時間を求める
//
int32 Timer::GetNextEvent()
{
uint32 ta = ((timera_count + 0xffff) >> 16) - 1;
uint32 tb = ((timerb_count + 0xfff) >> 12) - 1;
return (ta < tb ? ta : tb) + 1;
}
// ---------------------------------------------------------------------------
// タイマー基準値設定
//
void Timer::SetTimerBase(uint clock)
{
timer_step = int32(1000000. * 65536 / clock);
}
#else
// ---------------------------------------------------------------------------
// タイマーA 周期設定
//
void Timer::SetTimerA(uint addr, uint data)
{
regta[addr & 1] = uint8(data);
timera = (1024 - ((regta[0] << 2) + (regta[1] & 3))) << 16;
}
// ---------------------------------------------------------------------------
// タイマーB 周期設定
//
void Timer::SetTimerB(uint data)
{
timerb = (256-data) << (16 + 4);
}
// ---------------------------------------------------------------------------
// タイマー時間処理
//
bool Timer::Count(int32 us)
{
bool event = false;
int tick = us * timer_step;
if (timera_count)
{
timera_count -= tick;
if (timera_count <= 0)
{
event = true;
TimerA();
while (timera_count <= 0)
timera_count += timera;
if (regtc & 4)
SetStatus(1);
}
}
if (timerb_count)
{
timerb_count -= tick;
if (timerb_count <= 0)
{
event = true;
while (timerb_count <= 0)
timerb_count += timerb;
if (regtc & 8)
SetStatus(2);
}
}
return event;
}
// ---------------------------------------------------------------------------
// 次にタイマーが発生するまでの時間を求める
//
int32 Timer::GetNextEvent()
{
uint32 ta = timera_count - 1;
uint32 tb = timerb_count - 1;
uint32 t = (ta < tb ? ta : tb) + 1;
return (t+timer_step-1) / timer_step;
}
// ---------------------------------------------------------------------------
// タイマー基準値設定
//
void Timer::SetTimerBase(uint clock)
{
timer_step = clock * 1024 / 15625;
}
#endif
+53
View File
@@ -0,0 +1,53 @@
// ---------------------------------------------------------------------------
// FM sound generator common timer module
// Copyright (C) cisc 1998, 2000.
// ---------------------------------------------------------------------------
// $fmgen-Id: fmtimer.h,v 1.2 2003/04/22 13:12:53 cisc Exp $
#ifndef FM_TIMER_H
#define FM_TIMER_H
// ---------------------------------------------------------------------------
namespace FM
{
class Timer
{
public:
void Reset();
bool Count(int32 us);
int32 GetNextEvent();
protected:
virtual void SetStatus(uint bit) = 0;
virtual void ResetStatus(uint bit) = 0;
void SetTimerBase(uint clock);
void SetTimerA(uint addr, uint data);
void SetTimerB(uint data);
void SetTimerControl(uint data);
uint8 status;
uint8 regtc;
private:
virtual void TimerA() {}
uint8 regta[2];
int32 timera, timera_count;
int32 timerb, timerb_count;
int32 timer_step;
};
// ---------------------------------------------------------------------------
// ½é´ü²½
//
inline void Timer::Reset()
{
timera_count = 0;
timerb_count = 0;
}
} // namespace FM
#endif // FM_TIMER_H
+21
View File
@@ -0,0 +1,21 @@
#ifndef WIN_HEADERS_H
#define WIN_HEADERS_H
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#ifdef _MSC_VER
#undef max
#define max _MAX
#undef min
#define min _MIN
#endif
#endif // WIN_HEADERS_H
+69
View File
@@ -0,0 +1,69 @@
// ---------------------------------------------------------------------------
// misc.h
// Copyright (C) cisc 1998, 1999.
// ---------------------------------------------------------------------------
// $fmgen-Id: misc.h,v 1.5 2002/05/31 09:45:20 cisc Exp $
#ifndef MISC_H
#define MISC_H
inline int Max(int x, int y) { return (x > y) ? x : y; }
inline int Min(int x, int y) { return (x < y) ? x : y; }
inline int Abs(int x) { return x >= 0 ? x : -x; }
inline int Limit(int v, int max, int min)
{
return v > max ? max : (v < min ? min : v);
}
inline unsigned int BSwap(unsigned int a)
{
return (a >> 24) | ((a >> 8) & 0xff00) | ((a << 8) & 0xff0000) | (a << 24);
}
inline unsigned int NtoBCD(unsigned int a)
{
return ((a / 10) << 4) + (a % 10);
}
inline unsigned int BCDtoN(unsigned int v)
{
return (v >> 4) * 10 + (v & 15);
}
template<class T>
inline T gcd(T x, T y)
{
T t;
while (y)
{
t = x % y;
x = y;
y = t;
}
return x;
}
template<class T>
T bessel0(T x)
{
T p, r, s;
r = 1.0;
s = 1.0;
p = (x / 2.0) / s;
while (p > 1.0E-10)
{
r += p * p;
s += 1.0;
p *= (x / 2.0) / s;
}
return r;
}
#endif // MISC_H
+506
View File
@@ -0,0 +1,506 @@
// ---------------------------------------------------------------------------
// OPM interface
// Copyright (C) cisc 1998, 2003.
// ---------------------------------------------------------------------------
// $fmgen-Id: opm.cpp,v 1.26 2003/08/25 13:53:08 cisc Exp $
#include "headers.h"
#include "misc.h"
#include "opm.h"
#include "fmgeninl.h"
//#define LOGNAME "opm"
namespace FM
{
int OPM::amtable[4][OPM_LFOENTS] = { -1, };
int OPM::pmtable[4][OPM_LFOENTS];
// ---------------------------------------------------------------------------
// 構築
//
OPM::OPM()
{
lfo_count_ = 0;
lfo_count_prev_ = ~0;
BuildLFOTable();
for (int i=0; i<8; i++)
{
ch[i].SetChip(&chip);
ch[i].SetType(typeM);
}
}
// ---------------------------------------------------------------------------
// 初期化
//
bool OPM::Init(uint c, uint rf, bool ip)
{
if (!SetRate(c, rf, ip))
return false;
Reset();
SetVolume(0);
SetChannelMask(0);
return true;
}
// ---------------------------------------------------------------------------
// 再設定
//
bool OPM::SetRate(uint c, uint r, bool)
{
clock = c;
pcmrate = r;
rate = r;
RebuildTimeTable();
return true;
}
// ---------------------------------------------------------------------------
// チャンネルマスクの設定
//
void OPM::SetChannelMask(uint mask)
{
for (int i=0; i<8; i++)
ch[i].Mute(!!(mask & (1 << i)));
}
// ---------------------------------------------------------------------------
// リセット
//
void OPM::Reset()
{
int i;
for (i=0x0; i<0x100; i++) SetReg(i, 0);
SetReg(0x19, 0x80);
Timer::Reset();
status = 0;
noise = 12345;
noisecount = 0;
for (i=0; i<8; i++)
ch[i].Reset();
}
// ---------------------------------------------------------------------------
// 設定に依存するテーブルの作成
//
void OPM::RebuildTimeTable()
{
uint fmclock = clock / 64;
assert(fmclock < (0x80000000 >> FM_RATIOBITS));
rateratio = ((fmclock << FM_RATIOBITS) + rate/2) / rate;
SetTimerBase(fmclock);
// FM::MakeTimeTable(rateratio);
chip.SetRatio(rateratio);
// lfo_diff_ =
// lfodcount = (16 + (lfofreq & 15)) << (lfofreq >> 4);
// lfodcount = lfodcount * rateratio >> FM_RATIOBITS;
}
// ---------------------------------------------------------------------------
// タイマー A 発生時イベント (CSM)
//
void OPM::TimerA()
{
if (regtc & 0x80)
{
for (int i=0; i<8; i++)
{
ch[i].KeyControl(0);
ch[i].KeyControl(0xf);
}
}
}
// ---------------------------------------------------------------------------
// 音量設定
//
void OPM::SetVolume(int db)
{
db = Min(db, 20);
if (db > -192)
fmvolume = int(16384.0 * pow(10, db / 40.0));
else
fmvolume = 0;
}
// ---------------------------------------------------------------------------
// ステータスフラグ設定
//
void OPM::SetStatus(uint bits)
{
if (!(status & bits))
{
status |= bits;
Intr(true);
}
}
// ---------------------------------------------------------------------------
// ステータスフラグ解除
//
void OPM::ResetStatus(uint bits)
{
if (status & bits)
{
status &= ~bits;
if (!status)
Intr(false);
}
}
// ---------------------------------------------------------------------------
// レジスタアレイにデータを設定
//
void OPM::SetReg(uint addr, uint data)
{
if (addr >= 0x100)
return;
int c = addr & 7;
switch (addr & 0xff)
{
case 0x01: // TEST (lfo restart)
if (data & 2)
{
lfo_count_ = 0;
lfo_count_prev_ = ~0;
}
reg01 = data;
break;
case 0x08: // KEYON
if (!(regtc & 0x80))
ch[data & 7].KeyControl(data >> 3);
else
{
c = data & 7;
if (!(data & 0x08)) ch[c].op[0].KeyOff();
if (!(data & 0x10)) ch[c].op[1].KeyOff();
if (!(data & 0x20)) ch[c].op[2].KeyOff();
if (!(data & 0x40)) ch[c].op[3].KeyOff();
}
break;
case 0x10: case 0x11: // CLKA1, CLKA2
SetTimerA(addr, data);
break;
case 0x12: // CLKB
SetTimerB(data);
break;
case 0x14: // CSM, TIMER
SetTimerControl(data);
break;
case 0x18: // LFRQ(lfo freq)
lfofreq = data;
assert(16-4-FM_RATIOBITS >= 0);
lfo_count_diff_ =
rateratio
* ((16 + (lfofreq & 15)) << (16 - 4 - FM_RATIOBITS))
/ (1 << (15 - (lfofreq >> 4)));
break;
case 0x19: // PMD/AMD
(data & 0x80 ? pmd : amd) = data & 0x7f;
break;
case 0x1b: // CT, W(lfo waveform)
lfowaveform = data & 3;
break;
// RL, FB, Connect
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x24: case 0x25: case 0x26: case 0x27:
ch[c].SetFB((data >> 3) & 7);
ch[c].SetAlgorithm(data & 7);
pan[c] = (data >> 6) & 3;
break;
// KC
case 0x28: case 0x29: case 0x2a: case 0x2b:
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
kc[c] = data;
ch[c].SetKCKF(kc[c], kf[c]);
break;
// KF
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x34: case 0x35: case 0x36: case 0x37:
kf[c] = data >> 2;
ch[c].SetKCKF(kc[c], kf[c]);
break;
// PMS, AMS
case 0x38: case 0x39: case 0x3a: case 0x3b:
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
ch[c].SetMS((data << 4) | (data >> 4));
break;
case 0x0f: // NE/NFRQ (noise)
noisedelta = data;
noisecount = 0;
break;
default:
if (addr >= 0x40)
OPM::SetParameter(addr, data);
break;
}
}
// ---------------------------------------------------------------------------
// パラメータセット
//
void OPM::SetParameter(uint addr, uint data)
{
static const uint8 sltable[16] =
{
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, 52, 56, 124,
};
static const uint8 slottable[4] = { 0, 2, 1, 3 };
uint slot = slottable[(addr >> 3) & 3];
Operator* op = &ch[addr & 7].op[slot];
switch ((addr >> 5) & 7)
{
case 2: // 40-5F DT1/MULTI
op->SetDT((data >> 4) & 0x07);
op->SetMULTI(data & 0x0f);
break;
case 3: // 60-7F TL
op->SetTL(data & 0x7f, (regtc & 0x80) != 0);
break;
case 4: // 80-9F KS/AR
op->SetKS((data >> 6) & 3);
op->SetAR((data & 0x1f) * 2);
break;
case 5: // A0-BF DR/AMON(D1R/AMS-EN)
op->SetDR((data & 0x1f) * 2);
op->SetAMON((data & 0x80) != 0);
break;
case 6: // C0-DF SR(D2R), DT2
op->SetSR((data & 0x1f) * 2);
op->SetDT2((data >> 6) & 3);
break;
case 7: // E0-FF SL(D1L)/RR
op->SetSL(sltable[(data >> 4) & 15]);
op->SetRR((data & 0x0f) * 4 + 2);
break;
}
}
// ---------------------------------------------------------------------------
//
//
void OPM::BuildLFOTable()
{
if (amtable[0][0] != -1)
return;
for (int type=0; type<4; type++)
{
int r = 0;
for (int c=0; c<OPM_LFOENTS; c++)
{
int a, p;
switch (type)
{
case 0:
p = (((c + 0x100) & 0x1ff) / 2) - 0x80;
a = 0xff - c / 2;
break;
case 1:
a = c < 0x100 ? 0xff : 0;
p = c < 0x100 ? 0x7f : -0x80;
break;
case 2:
p = (c + 0x80) & 0x1ff;
p = p < 0x100 ? p - 0x80 : 0x17f - p;
a = c < 0x100 ? 0xff - c : c - 0x100;
break;
case 3:
if (!(c & 3))
r = (rand() / 17) & 0xff;
a = r;
p = r - 0x80;
break;
default: // XXX
a = 0;
p = 0;
break;
}
amtable[type][c] = a;
pmtable[type][c] = -p-1;
// printf("%d ", p);
}
}
}
// ---------------------------------------------------------------------------
inline void OPM::LFO()
{
if (lfowaveform != 3)
{
// if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 15) - 1))
{
int c = (lfo_count_ >> 15) & 0x1fe;
// fprintf(stderr, "%.8x %.2x\n", lfo_count_, c);
chip.SetPML(pmtable[lfowaveform][c] * pmd / 128 + 0x80);
chip.SetAML(amtable[lfowaveform][c] * amd / 128);
}
}
else
{
if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 17) - 1))
{
int c = (rand() / 17) & 0xff;
chip.SetPML((c - 0x80) * pmd / 128 + 0x80);
chip.SetAML(c * amd / 128);
}
}
lfo_count_prev_ = lfo_count_;
lfo_step_++;
if ((lfo_step_ & 7) == 0)
{
lfo_count_ += lfo_count_diff_;
}
}
inline uint OPM::Noise()
{
noisecount += 2 * rateratio;
if (noisecount >= (32 << FM_RATIOBITS))
{
int n = 32 - (noisedelta & 0x1f);
if (n == 1)
n = 2;
noisecount = noisecount - (n << FM_RATIOBITS);
if ((noisedelta & 0x1f) == 0x1f)
noisecount -= FM_RATIOBITS;
noise = (noise >> 1) ^ (noise & 1 ? 0x8408 : 0);
}
return noise;
}
// ---------------------------------------------------------------------------
// 合成の一部
//
inline void OPM::MixSub(int activech, ISample** idest)
{
if (activech & 0x4000) (*idest[0] = ch[0].Calc());
if (activech & 0x1000) (*idest[1] += ch[1].Calc());
if (activech & 0x0400) (*idest[2] += ch[2].Calc());
if (activech & 0x0100) (*idest[3] += ch[3].Calc());
if (activech & 0x0040) (*idest[4] += ch[4].Calc());
if (activech & 0x0010) (*idest[5] += ch[5].Calc());
if (activech & 0x0004) (*idest[6] += ch[6].Calc());
if (activech & 0x0001)
{
if (noisedelta & 0x80)
*idest[7] += ch[7].CalcN(Noise());
else
*idest[7] += ch[7].Calc();
}
}
inline void OPM::MixSubL(int activech, ISample** idest)
{
if (activech & 0x4000) (*idest[0] = ch[0].CalcL());
if (activech & 0x1000) (*idest[1] += ch[1].CalcL());
if (activech & 0x0400) (*idest[2] += ch[2].CalcL());
if (activech & 0x0100) (*idest[3] += ch[3].CalcL());
if (activech & 0x0040) (*idest[4] += ch[4].CalcL());
if (activech & 0x0010) (*idest[5] += ch[5].CalcL());
if (activech & 0x0004) (*idest[6] += ch[6].CalcL());
if (activech & 0x0001)
{
if (noisedelta & 0x80)
*idest[7] += ch[7].CalcLN(Noise());
else
*idest[7] += ch[7].CalcL();
}
}
// ---------------------------------------------------------------------------
// 合成 (stereo)
//
void OPM::Mix(Sample* buffer, int nsamples)
{
#define IStoSample(s) ((Limit(s, 0xffff, -0x10000) * fmvolume) >> 14)
//#define IStoSample(s) ((s * fmvolume) >> 14)
// odd bits - active, even bits - lfo
uint activech=0;
for (int i=0; i<8; i++)
activech = (activech << 2) | ch[i].Prepare();
if (activech & 0x5555)
{
// LFO 波形初期化ビット = 1 ならば LFO はかからない?
if (reg01 & 0x02)
activech &= 0x5555;
// Mix
ISample ibuf[8];
ISample* idest[8];
idest[0] = &ibuf[pan[0]];
idest[1] = &ibuf[pan[1]];
idest[2] = &ibuf[pan[2]];
idest[3] = &ibuf[pan[3]];
idest[4] = &ibuf[pan[4]];
idest[5] = &ibuf[pan[5]];
idest[6] = &ibuf[pan[6]];
idest[7] = &ibuf[pan[7]];
Sample* limit = buffer + nsamples * 2;
for (Sample* dest = buffer; dest < limit; dest+=2)
{
ibuf[1] = ibuf[2] = ibuf[3] = 0;
if (activech & 0xaaaa)
LFO(), MixSubL(activech, idest);
else
LFO(), MixSub(activech, idest);
StoreSample(dest[0], IStoSample(ibuf[1] + ibuf[3]));
StoreSample(dest[1], IStoSample(ibuf[2] + ibuf[3]));
}
}
#undef IStoSample
}
} // namespace FM
+161
View File
@@ -0,0 +1,161 @@
// ---------------------------------------------------------------------------
// OPM-like Sound Generator
// Copyright (C) cisc 1998, 2003.
// ---------------------------------------------------------------------------
// $fmgen-Id: opm.h,v 1.14 2003/06/07 08:25:53 cisc Exp $
#ifndef FM_OPM_H
#define FM_OPM_H
#include "fmgen.h"
#include "fmtimer.h"
#include "psg.h"
// ---------------------------------------------------------------------------
// class OPM
// OPM に良く似た(?)音を生成する音源ユニット
//
// interface:
// bool Init(uint clock, uint rate, bool);
// 初期化.このクラスを使用する前にかならず呼んでおくこと.
// 注意: 線形補完モードは廃止されました
//
// clock: OPM のクロック周波数(Hz)
//
// rate: 生成する PCM の標本周波数(Hz)
//
//
// 返値 初期化に成功すれば true
//
// bool SetRate(uint clock, uint rate, bool)
// クロックや PCM レートを変更する
// 引数等は Init と同様.
//
// void Mix(Sample* dest, int nsamples)
// Stereo PCM データを nsamples 分合成し, dest で始まる配列に
// 加える(加算する)
// ・dest には sample*2 個分の領域が必要
// ・格納形式は L, R, L, R... となる.
// ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある
// ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる.
// ・この関数は音源内部のタイマーとは独立している.
// Timer は Count と GetNextEvent で操作する必要がある.
//
// void Reset()
// 音源をリセット(初期化)する
//
// void SetReg(uint reg, uint data)
// 音源のレジスタ reg に data を書き込む
//
// uint ReadStatus()
// 音源のステータスレジスタを読み出す
// busy フラグは常に 0
//
// bool Count(uint32 t)
// 音源のタイマーを t [10^(-6) 秒] 進める.
// 音源の内部状態に変化があった時(timer オーバーフロー)
// true を返す
//
// uint32 GetNextEvent()
// 音源のタイマーのどちらかがオーバーフローするまでに必要な
// 時間[μ秒]を返す
// タイマーが停止している場合は 0 を返す.
//
// void SetVolume(int db)
// 各音源の音量を+-方向に調節する.標準値は 0.
// 単位は約 1/2 dB,有効範囲の上限は 20 (10dB)
//
// 仮想関数:
// virtual void Intr(bool irq)
// IRQ 出力に変化があった場合呼ばれる.
// irq = true: IRQ 要求が発生
// irq = false: IRQ 要求が消える
//
namespace FM
{
// YM2151(OPM) ----------------------------------------------------
class OPM : public Timer
{
public:
OPM();
virtual ~OPM() {}
bool Init(uint c, uint r, bool=false);
bool SetRate(uint c, uint r, bool);
void SetLPFCutoff(uint freq);
void Reset();
void SetReg(uint addr, uint data);
uint GetReg(uint addr);
uint ReadStatus() { return status & 0x03; }
void Mix(Sample* buffer, int nsamples);
void SetVolume(int db);
void SetChannelMask(uint mask);
private:
virtual void Intr(bool) {}
private:
enum
{
OPM_LFOENTS = 512,
};
void SetStatus(uint bit);
void ResetStatus(uint bit);
void SetParameter(uint addr, uint data);
void TimerA();
void RebuildTimeTable();
void MixSub(int activech, ISample**);
void MixSubL(int activech, ISample**);
void LFO();
uint Noise();
int fmvolume;
uint clock;
uint rate;
uint pcmrate;
uint pmd;
uint amd;
uint lfocount;
uint lfodcount;
uint lfo_count_;
uint lfo_count_diff_;
uint lfo_step_;
uint lfo_count_prev_;
uint lfowaveform;
uint rateratio;
uint noise;
int32 noisecount;
uint32 noisedelta;
bool interpolation;
uint8 lfofreq;
uint8 status;
uint8 reg01;
uint8 kc[8];
uint8 kf[8];
uint8 pan[8];
Channel4 ch[8];
Chip chip;
static void BuildLFOTable();
static int amtable[4][OPM_LFOENTS];
static int pmtable[4][OPM_LFOENTS];
public:
int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
Channel4* dbgGetCh(int c) { return &ch[c]; }
};
}
#endif // FM_OPM_H
+2197
View File
File diff suppressed because it is too large. Load diff
+464
View File
@@ -0,0 +1,464 @@
// ---------------------------------------------------------------------------
// OPN/A/B interface with ADPCM support
// Copyright (C) cisc 1998, 2003.
// ---------------------------------------------------------------------------
// $fmgen-Id: opna.h,v 1.33 2003/06/12 13:14:37 cisc Exp $
#ifndef FM_OPNA_H
#define FM_OPNA_H
#include "fmgen.h"
#include "fmtimer.h"
#include "psg.h"
// ---------------------------------------------------------------------------
// class OPN/OPNA
// OPN/OPNA に良く似た音を生成する音源ユニット
//
// interface:
// bool Init(uint clock, uint rate, bool, const char* path);
// 初期化.このクラスを使用する前にかならず呼んでおくこと.
// OPNA の場合はこの関数でリズムサンプルを読み込む
//
// clock: OPN/OPNA/OPNB のクロック周波数(Hz)
//
// rate: 生成する PCM の標本周波数(Hz)
//
// path: リズムサンプルのパス(OPNA のみ有効)
// 省略時はカレントディレクトリから読み込む
// 文字列の末尾には '\' や '/' などをつけること
//
// 返り値 初期化に成功すれば true
//
// bool LoadRhythmSample(const char* path)
// (OPNA ONLY)
// Rhythm サンプルを読み直す.
// path は Init の path と同じ.
//
// bool SetRate(uint clock, uint rate, bool)
// クロックや PCM レートを変更する
// 引数等は Init を参照のこと.
//
// void Mix(FM_SAMPLETYPE* dest, int nsamples)
// Stereo PCM データを nsamples 分合成し, dest で始まる配列に
// 加える(加算する)
// ・dest には sample*2 個分の領域が必要
// ・格納形式は L, R, L, R... となる.
// ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある
// ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる.
// ・この関数は音源内部のタイマーとは独立している.
// Timer は Count と GetNextEvent で操作する必要がある.
//
// void Reset()
// 音源をリセット(初期化)する
//
// void SetReg(uint reg, uint data)
// 音源のレジスタ reg に data を書き込む
//
// uint GetReg(uint reg)
// 音源のレジスタ reg の内容を読み出す
// 読み込むことが出来るレジスタは PSG, ADPCM の一部,ID(0xff) とか
//
// uint ReadStatus()/ReadStatusEx()
// 音源のステータスレジスタを読み出す
// ReadStatusEx は拡張ステータスレジスタの読み出し(OPNA)
// busy フラグは常に 0
//
// bool Count(uint32 t)
// 音源のタイマーを t [μ秒] 進める.
// 音源の内部状態に変化があった時(timer オーバーフロー)
// true を返す
//
// uint32 GetNextEvent()
// 音源のタイマーのどちらかがオーバーフローするまでに必要な
// 時間[μ秒]を返す
// タイマーが停止している場合は ULONG_MAX を返す… と思う
//
// void SetVolumeFM(int db)/SetVolumePSG(int db) ...
// 各音源の音量を+-方向に調節する.標準値は 0.
// 単位は約 1/2 dB,有効範囲の上限は 20 (10dB)
//
namespace FM
{
// OPN Base -------------------------------------------------------
class OPNBase : public Timer
{
public:
OPNBase();
virtual ~OPNBase() {}
bool Init(uint c, uint r);
virtual void Reset();
void SetVolumeFM(int db);
void SetVolumePSG(int db);
void SetLPFCutoff(uint freq) {} // obsolete
protected:
void SetParameter(Channel4* ch, uint addr, uint data);
void SetPrescaler(uint p);
void RebuildTimeTable();
int fmvolume;
uint clock; // OPN クロック
uint rate; // FM 音源合成レート
uint psgrate; // FMGen 出力レート
uint status;
Channel4* csmch;
static uint32 lfotable[8];
private:
void TimerA();
uint8 prescale;
protected:
Chip chip;
PSG psg;
};
// OPN2 Base ------------------------------------------------------
class OPNABase : public OPNBase
{
public:
OPNABase();
virtual ~OPNABase();
uint ReadStatus() { return status & 0x03; }
uint ReadStatusEx();
void SetChannelMask(uint mask);
private:
virtual void Intr(bool) {}
void MakeTable2();
protected:
bool Init(uint c, uint r, bool);
bool SetRate(uint c, uint r, bool);
void Reset();
void SetReg(uint addr, uint data);
void SetADPCMBReg(uint reg, uint data);
uint GetReg(uint addr);
protected:
void FMMix(Sample* buffer, int nsamples);
void Mix6(Sample* buffer, int nsamples, int activech);
void MixSubS(int activech, ISample**);
void MixSubSL(int activech, ISample**);
void SetStatus(uint bit);
void ResetStatus(uint bit);
void UpdateStatus();
void LFO();
void DecodeADPCMB();
void ADPCMBMix(Sample* dest, uint count);
void WriteRAM(uint data);
uint ReadRAM();
int ReadRAMN();
int DecodeADPCMBSample(uint);
// FM 音源関係
uint8 pan[6];
uint8 fnum2[9];
uint8 reg22;
uint reg29; // OPNA only?
uint stmask;
uint statusnext;
uint32 lfocount;
uint32 lfodcount;
uint fnum[6];
uint fnum3[3];
// ADPCM 関係
uint8* adpcmbuf; // ADPCM RAM
uint adpcmmask; // メモリアドレスに対するビットマスク
uint adpcmnotice; // ADPCM 再生終了時にたつビット
uint startaddr; // Start address
uint stopaddr; // Stop address
uint memaddr; // 再生中アドレス
uint limitaddr; // Limit address/mask
int adpcmlevel; // ADPCM 音量
int adpcmvolume;
int adpcmvol;
uint deltan; // ⊿N
int adplc; // 周波数変換用変数
int adpld; // 周波数変換用変数差分値
uint adplbase; // adpld の元
int adpcmx; // ADPCM 合成用 x
int adpcmd; // ADPCM 合成用 ⊿
int adpcmout; // ADPCM 合成後の出力
int apout0; // out(t-2)+out(t-1)
int apout1; // out(t-1)+out(t)
uint adpcmreadbuf; // ADPCM リード用バッファ
bool adpcmplay; // ADPCM 再生中
int8 granuality;
bool adpcmmask_;
uint8 control1; // ADPCM コントロールレジスタ1
uint8 control2; // ADPCM コントロールレジスタ2
uint8 adpcmreg[8]; // ADPCM レジスタの一部分
int rhythmmask_;
Channel4 ch[6];
static void BuildLFOTable();
static int amtable[FM_LFOENTS];
static int pmtable[FM_LFOENTS];
static int32 tltable[FM_TLENTS+FM_TLPOS];
static bool tablehasmade;
};
// YM2203(OPN) ----------------------------------------------------
class OPN : public OPNBase
{
public:
OPN();
virtual ~OPN() {}
bool Init(uint c, uint r, bool=false, const char* =0);
bool SetRate(uint c, uint r, bool=false);
void Reset();
void Mix(Sample* buffer, int nsamples);
void SetReg(uint addr, uint data);
uint GetReg(uint addr);
uint ReadStatus() { return status & 0x03; }
uint ReadStatusEx() { return 0xff; }
void SetChannelMask(uint mask);
int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
int dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; }
Channel4* dbgGetCh(int c) { return &ch[c]; }
private:
virtual void Intr(bool) {}
void SetStatus(uint bit);
void ResetStatus(uint bit);
uint fnum[3];
uint fnum3[3];
uint8 fnum2[6];
Channel4 ch[3];
};
// YM2608(OPNA) ---------------------------------------------------
class OPNA : public OPNABase
{
public:
OPNA();
virtual ~OPNA();
bool Init(uint c, uint r, bool = false, const char* rhythmpath=0);
bool LoadRhythmSample(const char*);
bool SetRate(uint c, uint r, bool = false);
void Mix(Sample* buffer, int nsamples);
void Reset();
void SetReg(uint addr, uint data);
uint GetReg(uint addr);
void SetVolumeADPCM(int db);
void SetVolumeRhythmTotal(int db);
void SetVolumeRhythm(int index, int db);
uint8* GetADPCMBuffer() { return adpcmbuf; }
int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; }
int dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; }
Channel4* dbgGetCh(int c) { return &ch[c]; }
private:
struct Rhythm
{
uint8 pan; // ぱん
int8 level; // おんりょう
int volume; // おんりょうせってい
int16* sample; // さんぷる
uint size; // さいず
uint pos; // いち
uint step; // すてっぷち
uint rate; // さんぷるのれーと
};
void RhythmMix(Sample* buffer, uint count);
// リズム音源関係
Rhythm rhythm[6];
int8 rhythmtl; // リズム全体の音量
int rhythmtvol;
uint8 rhythmkey; // リズムのキー
};
// YM2610/B(OPNB) ---------------------------------------------------
class OPNB : public OPNABase
{
public:
OPNB();
virtual ~OPNB();
bool Init(uint c, uint r, bool = false,
uint8 *_adpcma = 0, int _adpcma_size = 0,
uint8 *_adpcmb = 0, int _adpcmb_size = 0);
bool SetRate(uint c, uint r, bool = false);
void Mix(Sample* buffer, int nsamples);
void Reset();
void SetReg(uint addr, uint data);
uint GetReg(uint addr);
uint ReadStatusEx();
void SetVolumeADPCMATotal(int db);
void SetVolumeADPCMA(int index, int db);
void SetVolumeADPCMB(int db);
// void SetChannelMask(uint mask);
private:
struct ADPCMA
{
uint8 pan; // ぱん
int8 level; // おんりょう
int volume; // おんりょうせってい
uint pos; // いち
uint step; // すてっぷち
uint start; // 開始
uint stop; // 終了
uint nibble; // 次の 4 bit
int adpcmx; // 変換用
int adpcmd; // 変換用
};
int DecodeADPCMASample(uint);
void ADPCMAMix(Sample* buffer, uint count);
static void InitADPCMATable();
// ADPCMA 関係
uint8* adpcmabuf; // ADPCMA ROM
int adpcmasize;
ADPCMA adpcma[6];
int8 adpcmatl; // ADPCMA 全体の音量
int adpcmatvol;
uint8 adpcmakey; // ADPCMA のキー
int adpcmastep;
uint8 adpcmareg[32];
static int jedi_table[(48+1)*16];
Channel4 ch[6];
};
// YM2612/3438(OPN2) ----------------------------------------------------
class OPN2 : public OPNBase
{
public:
OPN2();
virtual ~OPN2() {}
bool Init(uint c, uint r, bool=false, const char* =0);
bool SetRate(uint c, uint r, bool);
void Reset();
void Mix(Sample* buffer, int nsamples);
void SetReg(uint addr, uint data);
uint GetReg(uint addr);
uint ReadStatus() { return status & 0x03; }
uint ReadStatusEx() { return 0xff; }
void SetChannelMask(uint mask);
private:
virtual void Intr(bool) {}
void SetStatus(uint bit);
void ResetStatus(uint bit);
uint fnum[3];
uint fnum3[3];
uint8 fnum2[6];
// 線形補間用ワーク
int32 mixc, mixc1;
Channel4 ch[3];
};
// YMF288 ---------------------------------------------------
class Y288 : public OPNABase
{
public:
Y288();
virtual ~Y288();
bool Init(uint c, uint r, bool ipflag = false, const char* =0);
bool LoadRhythmSample(const char*);
bool SetRate(uint c, uint r, bool ipflag = false);
void Mix(Sample* buffer, int nsamples);
void SetVolumeRhythmTotal(int db);
void SetVolumeRhythm(int index, int db);
void Reset();
void SetReg(uint addr, uint data);
uint GetReg(uint addr);
private:
struct Rhythm
{
uint8 pan; // ぱん
int8 level; // おんりょう
int volume; // おんりょうせってい
int16* sample; // さんぷる
uint size; // さいず
uint pos; // いち
uint step; // すてっぷち
uint rate; // さんぷるのれーと
};
void RhythmMix(Sample* buffer, uint count);
// リズム音源関係
Rhythm rhythm[6];
int8 rhythmtl; // リズム全体の音量
int rhythmtvol;
uint8 rhythmkey; // リズムのキー
int mode288; // 288/2608モードフラグ
};
}
// ---------------------------------------------------------------------------
inline void FM::OPNBase::RebuildTimeTable()
{
int p = prescale;
prescale = (uint8)-1;
SetPrescaler(p);
}
inline void FM::OPNBase::SetVolumePSG(int db)
{
psg.SetVolume(db);
}
#endif // FM_OPNA_H
+364
View File
@@ -0,0 +1,364 @@
// ---------------------------------------------------------------------------
// PSG Sound Implementation
// Copyright (C) cisc 1997, 1999.
// ---------------------------------------------------------------------------
// $fmgen-Id: psg.cpp,v 1.10 2002/05/15 21:38:01 cisc Exp $
#include "common.h"
#include "fmgen_types.h"
#include "headers.h"
#include "misc.h"
#include "psg.h"
// ---------------------------------------------------------------------------
// コンストラクタ・デストラクタ
//
PSG::PSG()
{
SetVolume(0);
MakeNoiseTable();
Reset();
mask = 0x3f;
}
PSG::~PSG()
{
}
// ---------------------------------------------------------------------------
// PSG を初期化する(RESET)
//
void PSG::Reset()
{
for (int i=0; i<14; i++)
SetReg(i, 0);
SetReg(7, 0xff);
SetReg(14, 0xff);
SetReg(15, 0xff);
}
// ---------------------------------------------------------------------------
// クロック周波数の設定
//
void PSG::SetClock(int clock, int rate)
{
tperiodbase = int((1 << toneshift ) / 4.0 * clock / rate);
eperiodbase = int((1 << envshift ) / 4.0 * clock / rate);
nperiodbase = int((1 << noiseshift) / 4.0 * clock / rate);
// 各データの更新
int tmp;
tmp = ((reg[0] + reg[1] * 256) & 0xfff);
speriod[0] = tmp ? tperiodbase / tmp : tperiodbase;
tmp = ((reg[2] + reg[3] * 256) & 0xfff);
speriod[1] = tmp ? tperiodbase / tmp : tperiodbase;
tmp = ((reg[4] + reg[5] * 256) & 0xfff);
speriod[2] = tmp ? tperiodbase / tmp : tperiodbase;
tmp = reg[6] & 0x1f;
nperiod = tmp ? nperiodbase / tmp / 2 : nperiodbase / 2;
tmp = ((reg[11] + reg[12] * 256) & 0xffff);
eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
}
// ---------------------------------------------------------------------------
// ノイズテーブルを作成する
//
void PSG::MakeNoiseTable()
{
if (!noisetable[0])
{
int noise = 14321;
for (int i=0; i<noisetablesize; i++)
{
int n = 0;
for (int j=0; j<32; j++)
{
n = n * 2 + (noise & 1);
noise = (noise >> 1) | (((noise << 14) ^ (noise << 16)) & 0x10000);
}
noisetable[i] = n;
}
}
}
// ---------------------------------------------------------------------------
// 出力テーブルを作成
// 素直にテーブルで持ったほうが省スペース。
//
void PSG::SetVolume(int volume)
{
double base = 0x4000 / 3.0 * pow(10.0, volume / 40.0);
for (int i=31; i>=2; i--)
{
EmitTable[i] = int(base);
base /= 1.189207115;
}
EmitTable[1] = 0;
EmitTable[0] = 0;
MakeEnvelopTable();
SetChannelMask(~mask);
}
void PSG::SetChannelMask(int c)
{
mask = ~c;
for (int i=0; i<3; i++)
olevel[i] = mask & (1 << i) ? EmitTable[(reg[8+i] & 15) * 2 + 1] : 0;
}
// ---------------------------------------------------------------------------
// エンベロープ波形テーブル
//
void PSG::MakeEnvelopTable()
{
// 0 lo 1 up 2 down 3 hi
static uint8 table1[16*2] =
{
2,0, 2,0, 2,0, 2,0, 1,0, 1,0, 1,0, 1,0,
2,2, 2,0, 2,1, 2,3, 1,1, 1,3, 1,2, 1,0,
};
static uint8 table2[4] = { 0, 0, 31, 31 };
static uint8 table3[4] = { 0, 1, (uint8)-1, 0 };
uint* ptr = enveloptable[0];
for (int i=0; i<16*2; i++)
{
uint8 v = table2[table1[i]];
for (int j=0; j<32; j++)
{
*ptr++ = EmitTable[v];
v += table3[table1[i]];
}
}
}
// ---------------------------------------------------------------------------
// PSG のレジスタに値をセットする
// regnum レジスタの番号 (0 - 15)
// data セットする値
//
void PSG::SetReg(uint regnum, uint8 data)
{
if (regnum < 0x10)
{
reg[regnum] = data;
switch (regnum)
{
int tmp;
case 0: // ChA Fine Tune
case 1: // ChA Coarse Tune
tmp = ((reg[0] + reg[1] * 256) & 0xfff);
speriod[0] = tmp ? tperiodbase / tmp : tperiodbase;
break;
case 2: // ChB Fine Tune
case 3: // ChB Coarse Tune
tmp = ((reg[2] + reg[3] * 256) & 0xfff);
speriod[1] = tmp ? tperiodbase / tmp : tperiodbase;
break;
case 4: // ChC Fine Tune
case 5: // ChC Coarse Tune
tmp = ((reg[4] + reg[5] * 256) & 0xfff);
speriod[2] = tmp ? tperiodbase / tmp : tperiodbase;
break;
case 6: // Noise generator control
data &= 0x1f;
nperiod = data ? nperiodbase / data : nperiodbase;
break;
case 8:
olevel[0] = mask & 1 ? EmitTable[(data & 15) * 2 + 1] : 0;
break;
case 9:
olevel[1] = mask & 2 ? EmitTable[(data & 15) * 2 + 1] : 0;
break;
case 10:
olevel[2] = mask & 4 ? EmitTable[(data & 15) * 2 + 1] : 0;
break;
case 11: // Envelop period
case 12:
tmp = ((reg[11] + reg[12] * 256) & 0xffff);
eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2;
break;
case 13: // Envelop shape
ecount = 0;
envelop = enveloptable[data & 15];
break;
}
}
}
// ---------------------------------------------------------------------------
//
//
inline void PSG::StoreSample(Sample& dest, int32 data)
{
if (sizeof(Sample) == 2)
dest = (Sample) Limit(dest + data, 0x7fff, -0x8000);
else
dest += data;
}
// ---------------------------------------------------------------------------
// PCM データを吐き出す(2ch)
// dest PCM データを展開するポインタ
// nsamples 展開する PCM のサンプル数
//
void PSG::Mix(Sample* dest, int nsamples)
{
uint8 chenable[3], nenable[3];
uint8 r7 = ~reg[7];
if ((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f))
{
chenable[0] = (r7 & 0x01) && (speriod[0] <= (1 << toneshift));
chenable[1] = (r7 & 0x02) && (speriod[1] <= (1 << toneshift));
chenable[2] = (r7 & 0x04) && (speriod[2] <= (1 << toneshift));
nenable[0] = (r7 >> 3) & 1;
nenable[1] = (r7 >> 4) & 1;
nenable[2] = (r7 >> 5) & 1;
int noise, sample;
uint env;
uint* p1 = ((mask & 1) && (reg[ 8] & 0x10)) ? &env : &olevel[0];
uint* p2 = ((mask & 2) && (reg[ 9] & 0x10)) ? &env : &olevel[1];
uint* p3 = ((mask & 4) && (reg[10] & 0x10)) ? &env : &olevel[2];
#define SCOUNT(ch) (scount[ch] >> (toneshift+oversampling))
if (p1 != &env && p2 != &env && p3 != &env)
{
// エンベロープ無し
if ((r7 & 0x38) == 0)
{
// ノイズ無し
for (int i=0; i<nsamples; i++)
{
sample = 0;
for (int j=0; j < (1 << oversampling); j++)
{
int x, y, z;
x = (SCOUNT(0) & chenable[0]) - 1;
sample += (olevel[0] + x) ^ x;
scount[0] += speriod[0];
y = (SCOUNT(1) & chenable[1]) - 1;
sample += (olevel[1] + y) ^ y;
scount[1] += speriod[1];
z = (SCOUNT(2) & chenable[2]) - 1;
sample += (olevel[2] + z) ^ z;
scount[2] += speriod[2];
}
sample /= (1 << oversampling);
StoreSample(dest[0], sample);
StoreSample(dest[1], sample);
dest += 2;
}
}
else
{
// ノイズ有り
for (int i=0; i<nsamples; i++)
{
sample = 0;
for (int j=0; j < (1 << oversampling); j++)
{
#ifdef _M_IX86
noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
>> (ncount >> (noiseshift+oversampling+1));
#else
noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
>> (ncount >> (noiseshift+oversampling+1) & 31);
#endif
ncount += nperiod;
int x, y, z;
x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1
sample += (olevel[0] + x) ^ x;
scount[0] += speriod[0];
y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1;
sample += (olevel[1] + y) ^ y;
scount[1] += speriod[1];
z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1;
sample += (olevel[2] + z) ^ z;
scount[2] += speriod[2];
}
sample /= (1 << oversampling);
StoreSample(dest[0], sample);
StoreSample(dest[1], sample);
dest += 2;
}
}
// エンベロープの計算をさぼった帳尻あわせ
ecount = (ecount >> 8) + (eperiod >> (8-oversampling)) * nsamples;
if (ecount >= (1 << (envshift+6+oversampling-8)))
{
if ((reg[0x0d] & 0x0b) != 0x0a)
ecount |= (1 << (envshift+5+oversampling-8));
ecount &= (1 << (envshift+6+oversampling-8)) - 1;
}
ecount <<= 8;
}
else
{
// エンベロープあり
for (int i=0; i<nsamples; i++)
{
sample = 0;
for (int j=0; j < (1 << oversampling); j++)
{
env = envelop[ecount >> (envshift+oversampling)];
ecount += eperiod;
if (ecount >= (1 << (envshift+6+oversampling)))
{
if ((reg[0x0d] & 0x0b) != 0x0a)
ecount |= (1 << (envshift+5+oversampling));
ecount &= (1 << (envshift+6+oversampling)) - 1;
}
#ifdef _M_IX86
noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
>> (ncount >> (noiseshift+oversampling+1));
#else
noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)]
>> (ncount >> (noiseshift+oversampling+1) & 31);
#endif
ncount += nperiod;
int x, y, z;
x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1
sample += (*p1 + x) ^ x;
scount[0] += speriod[0];
y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1;
sample += (*p2 + y) ^ y;
scount[1] += speriod[1];
z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1;
sample += (*p3 + z) ^ z;
scount[2] += speriod[2];
}
sample /= (1 << oversampling);
StoreSample(dest[0], sample);
StoreSample(dest[1], sample);
dest += 2;
}
}
}
}
// ---------------------------------------------------------------------------
// テーブル
//
uint PSG::noisetable[noisetablesize] = { 0, };
int PSG::EmitTable[0x20] = { -1, };
uint PSG::enveloptable[16][64] = { 0, };
+93
View File
@@ -0,0 +1,93 @@
// ---------------------------------------------------------------------------
// PSG-like sound generator
// Copyright (C) cisc 1997, 1999.
// ---------------------------------------------------------------------------
// $fmgen-Id: psg.h,v 1.8 2003/04/22 13:12:53 cisc Exp $
#ifndef PSG_H
#define PSG_H
#define PSG_SAMPLETYPE int32 // int32 or int16
// ---------------------------------------------------------------------------
// class PSG
// PSG に良く似た音を生成する音源ユニット
//
// interface:
// bool SetClock(uint clock, uint rate)
// 初期化.このクラスを使用する前にかならず呼んでおくこと.
// PSG のクロックや PCM レートを設定する
//
// clock: PSG の動作クロック
// rate: 生成する PCM のレート
// retval 初期化に成功すれば true
//
// void Mix(Sample* dest, int nsamples)
// PCM を nsamples 分合成し, dest で始まる配列に加える(加算する)
// あくまで加算なので,最初に配列をゼロクリアする必要がある
//
// void Reset()
// リセットする
//
// void SetReg(uint reg, uint8 data)
// レジスタ reg に data を書き込む
//
// uint GetReg(uint reg)
// レジスタ reg の内容を読み出す
//
// void SetVolume(int db)
// 各音源の音量を調節する
// 単位は約 1/2 dB
//
class PSG
{
public:
typedef PSG_SAMPLETYPE Sample;
enum
{
noisetablesize = 1 << 11, // ←メモリ使用量を減らしたいなら減らして
toneshift = 24,
envshift = 22,
noiseshift = 14,
oversampling = 2, // ← 音質より速度が優先なら減らすといいかも
};
public:
PSG();
~PSG();
void Mix(Sample* dest, int nsamples);
void SetClock(int clock, int rate);
void SetVolume(int vol);
void SetChannelMask(int c);
void Reset();
void SetReg(uint regnum, uint8 data);
uint GetReg(uint regnum) { return reg[regnum & 0x0f]; }
protected:
void MakeNoiseTable();
void MakeEnvelopTable();
static void StoreSample(Sample& dest, int32 data);
uint8 reg[16];
const uint* envelop;
uint olevel[3];
uint32 scount[3], speriod[3];
uint32 ecount, eperiod;
uint32 ncount, nperiod;
uint32 tperiodbase;
uint32 eperiodbase;
uint32 nperiodbase;
int volume;
int mask;
static uint enveloptable[16][64];
static uint noisetable[noisetablesize];
static int EmitTable[32];
};
#endif // PSG_H
+93
View File
@@ -0,0 +1,93 @@
------------------------------------------------------------------------------
FM Sound Generator with OPN/OPM interface
Copyright (C) by cisc 1998, 2003.
------------------------------------------------------------------------------
【概要】
C++ による FM/PSG 音源の実装です。
AY8910, YM2203, YM2151, YM2608, YM2610 相当のインターフェースも
実装してあります。
【使い方】
(TODO:中身を書く)
【注意】
以前のバージョンから幾分手を加えました。インターフェースは
いじっていないつもりですが、何かしらのバグが隠れているかもしれません。
YM2610 は動作チェックすらしていません。
線形補完モード(interpolation)は廃止されました。
Init() の引数仕様は変わっていませんが、interpolation = true にしても
動作は変わりません。
OPNA::Init/SetRate で与えるチップクロックの値の仕様が
以前の M88 に搭載されていたバージョンと異なっています.
【著作権、免責規定】
・本ソースコードは作者([email protected]) が著作権を所有しています。
・本ソースコードはあるがままに提供されるものであり,
暗黙及び明示的な保証を一切含みません.
・本ソースコードを利用したこと,利用しなかったこと,
利用できなかったことに関して生じたあるいは生じると予測される
損害について,作者は一切責任を負いません.
・本ソースコードは,以下の制限を満たす限り自由に改変・組み込み・
配布・利用することができます.
1. 本ソフトの由来(作者, 著作権)を明記すること.
2. 配布する際にはフリーソフトとすること.
3. 改変したソースコードを配布する際は改変内容を明示すること.
4. ソースコードを配布する際にはこのテキストを一切改変せずに
そのまま添付すること.
・公開の際に作者への連絡を頂ければ幸いです.
・商用ソフト(シェアウェア含む) に本ソースコードの一部,または
全部を組み込む際には,事前に作者の合意を得る必要があります.
【変更点】
008 030902 ・出力サンプリングレートの設定を、チップ元来の合成サンプ
リングレートと異なる設定にするとエンベロープがおかしく
なる問題を修正。
007a 030608 ・領域外アクセスがあったのを修正 (Thanks to PI.様)
007 030607 ・再現性の向上
・OPN: SSG-EG のサポート
・線形補完の廃止
・asm 版の廃止
・マルチスレッドフリーになった?
006 010330 ・再現性に関していくらか手直し(正弦波,出力タイミング等)
005 010317 ・OPN: FM 音源の合成周波数が出力周波数よりも低いときに,
補完を使うと音痴になる/音がまともに出なくなる問題を修正.
・FM: 補完を使わない時の精度を上げてみる.
問題が起きたら fmgeninl.h の FM_RATIOBITS を 8 に戻すと吉.
004a 010311 ・OPM: ノイズをそこそこ聞けるレベル(?)まで修正.
・OPNA/OPM: FM_USE_CALC2 廃止.
・デグレ修正, なんのために cvs で管理しているんだか…(T-T
OPNB: ADPCMB ROM マスク作成ミス.
OPNB: ADPCMA ステータスフラグ関係の挙動修復.
OPM: LFO パラメータの初期化を忘れていたのを修正.
003 010124 ・OPNA/OPM: 実際には補完前の値を出力していたバグを修正.
002 010123 ・合成周波数が出力周波数より低いときでも補間が効くようにする.
・OPN: 補間時にプリスケーラの設定を変更したときに音化けする
バグを修正.
・OPNA/B: LFO が効かないバグを修正.
001 000928 ・初期バージョン
$fmgen-Id: readme.txt,v 1.1 2003/06/07 08:25:20 cisc Exp $
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

+26
View File
@@ -0,0 +1,26 @@
/* XPM */
static char *adpcm[] = {
/* columns rows colors chars-per-pixel */
"42 17 3 1",
" c black",
". c #808080",
"X c #C0C0C0",
/* pixels */
"X X XX X",
"X XX. X .XX XX XXXXXXXXXXXXXXXXXXXXX X",
"X XXXX X XXXX XX XX XX XX XXX X X X X",
"X XXXX. X .XXXX XX X X X X X X X XXX X X",
"X XXXXX X XXXXX XX X X X X X X X XXX X X",
"X XXXXX X XXXXX XX X X X X XX XXX X X X",
"X XXXX. X .XXXX XX X X X X X XXX XXX X X X",
"X XXXX X XXXX XX X X X XX XXXX X X X X",
"X XX. X .XX XX XXXXXXXXXXXXXXXXXXXXX X",
"X X XX X",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
" XXX XXX .XXX XX XX XXX XX",
" XX .XX XX. XX XX XXXX XXX. .XX XX",
" XX XX XX XXXXXX XXXX XXX X XX XX",
" XX XX XX XX XX XXXX XXX X XX XX",
" XX .XX XX. XX XX XXXX XX. .X XX",
" XXX XXX XX XXXX XX. .X. .X "
};
+26
View File
@@ -0,0 +1,26 @@
/* XPM */
static char *fd_inserted[] = {
/* width height ncolors chars_per_pixel */
"16 16 3 1",
/* colors */
" c #999999",
". c #C0C0C0",
"X c #585858",
/* pixels */
"................",
"................",
"..XXXXXXXXXX....",
"..X X X XX...",
"..X X X X X..",
"..X X X X..",
"..X XXXXXXXX X..",
"..X X..",
"..X XXXXXXXX X..",
"..X X X X..",
"..X X X X..",
"..X X X X..",
"..X X X X..",
"..XXXXXXXXXXXX..",
"................",
"................"
};
+26
View File
@@ -0,0 +1,26 @@
/* XPM */
static char *fd_inuse[] = {
/* width height ncolors chars_per_pixel */
"16 16 3 1",
/* colors */
" c #009F50",
". c #C0C0C0",
"X c #00E171",
/* pixels */
"................",
"................",
".. ....",
".. X XXXX X ...",
".. X XXXX X X ..",
".. X XXXXXX X ..",
".. X X ..",
".. XXXXXXXXXX ..",
".. X X ..",
".. X XXXXXX X ..",
".. X XXXXXX X ..",
".. X XXXXXX X ..",
".. X XXXXXX X ..",
".. ..",
"................",
"................"
};
+25
View File
@@ -0,0 +1,25 @@
/* XPM */
static char *fd_normal[] = {
/* width height ncolors chars_per_pixel */
"16 16 2 1",
/* colors */
" c #9B9B9B",
". c #C0C0C0",
/* pixels */
"................",
"................",
".. ....",
".. . .... . ...",
".. . .... . . ..",
".. . ...... . ..",
".. . . ..",
".. .......... ..",
".. . . ..",
".. . ...... . ..",
".. . ...... . ..",
".. . ...... . ..",
".. . ...... . ..",
".. ..",
"................",
"................"
};
+27
View File
@@ -0,0 +1,27 @@
/* XPM */
static char *fd_protected[] = {
/* width height ncolors chars_per_pixel */
"16 16 4 1",
/* colors */
" c #999999",
". c #8F2E2C",
"X c #C0C0C0",
"o c #585858",
/* pixels */
"XXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXX",
"XXooooooooooXXXX",
"XXo o o ooXXX",
"XXo o o o oXX",
"XXo o o oXX",
"XXo oooooooo oXX",
"XXo oXX",
"XXo oooooooo oXX",
"XXo o o oXX",
"XXo o ...XX",
"XXo o . ...X",
"XXo o . . .X",
"XXoooooooo... .X",
"XXXXXXXXXXX...XX",
"XXXXXXXXXXXXXXXX"
};
+26
View File
@@ -0,0 +1,26 @@
/* XPM */
static char *hd_inserted[] = {
/* width height ncolors chars_per_pixel */
"16 16 3 1",
/* colors */
" c #999999",
". c #C0C0C0",
"X c #585858",
/* pixels */
"................",
"................",
".....XXXXXX.....",
"...XX XX...",
"..X X..",
"..XXX XXX..",
"..X XXXXXX X..",
"..X X..",
"..X X..",
"..X X..",
"..X X..",
"..X X..",
"...XX XX...",
".....XXXXXX.....",
"................",
"................"
};
+26
View File
@@ -0,0 +1,26 @@
/* XPM */
static char *hd_inuse[] = {
/* width height ncolors chars_per_pixel */
"16 16 3 1",
/* colors */
" c #009F50",
". c #C0C0C0",
"X c #00E171",
/* pixels */
"................",
"................",
"..... .....",
"... XXXXXX ...",
".. XXXXXXXXXX ..",
".. XXXXXX ..",
".. XX XX ..",
".. XXXXXXXXXX ..",
".. XXXXXXXXXX ..",
".. XXXXXXXXXX ..",
".. XXXXXXXXXX ..",
".. XXXXXXXXXX ..",
"... XXXXXX ...",
"..... .....",
"................",
"................"
};
+25
View File
@@ -0,0 +1,25 @@
/* XPM */
static char *hd_normal[] = {
/* width height ncolors chars_per_pixel */
"16 16 2 1",
/* colors */
" c #9B9B9B",
". c #C0C0C0",
/* pixels */
"................",
"................",
"..... .....",
"... ...... ...",
".. .......... ..",
".. ...... ..",
".. .. .. ..",
".. .......... ..",
".. .......... ..",
".. .......... ..",
".. .......... ..",
".. .......... ..",
"... ...... ...",
"..... .....",
"................",
"................"
};
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+14
View File
@@ -0,0 +1,14 @@
#define keropi_width 32
#define keropi_height 32
static char keropi_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0xE0, 0x1D, 0x00, 0x00, 0xF0, 0x6F, 0x00,
0x00, 0xD0, 0xFF, 0x00, 0x6D, 0xE4, 0xFC, 0x00, 0xE2, 0xEE, 0xBF, 0x00,
0x1A, 0xF2, 0xFF, 0x00, 0x44, 0xEA, 0xFF, 0x01, 0xBB, 0xF4, 0xFF, 0x01,
0x12, 0xA9, 0xBF, 0x00, 0x55, 0x6A, 0xDF, 0x00, 0xD4, 0xD5, 0xD7, 0x00,
0x26, 0xAA, 0xB6, 0x00, 0x9A, 0x95, 0xED, 0x01, 0x24, 0x5D, 0x96, 0x03,
0x51, 0xD5, 0xE6, 0x06, 0xA6, 0xAA, 0x3D, 0x07, 0x49, 0x3D, 0xDE, 0x07,
0xB6, 0x92, 0xAF, 0x0E, 0xA9, 0xE8, 0xB7, 0x0D, 0x94, 0xBF, 0x69, 0x0F,
0xFF, 0x9F, 0x66, 0x0D, 0x56, 0xE1, 0xDC, 0x1A, };
+112
View File
@@ -0,0 +1,112 @@
/* XPM */
static char *keropi_xpm[] = {
/* columns rows colors chars-per-pixel */
"64 64 40 1",
" c black",
". c #2A1F00",
"X c #2A3F00",
"o c #2A1F55",
"O c #2A3F55",
"+ c #2A5F00",
"@ c #007F55",
"# c #2A5F55",
"$ c #2A7F55",
"% c #553F55",
"& c #555F55",
"* c #557F55",
"= c #7F5F55",
"- c #009F55",
"; c #00BF55",
": c #2A9F55",
"> c #2ABF55",
", c #2ADF55",
"< c #559F55",
"1 c #55BF55",
"2 c #55DF55",
"3 c #7FDF55",
"4 c #2ABFAA",
"5 c #2ADFAA",
"6 c #559FAA",
"7 c #55BFAA",
"8 c #7FBFAA",
"9 c #55DFAA",
"0 c #7FDFAA",
"q c #7FFFAA",
"w c #808080",
"e c #AA9FAA",
"r c #A0A0A4",
"t c #AABFAA",
"y c #AAFFAA",
"u c #C0DCC0",
"i c #CCCCFF",
"p c #D4DFFF",
"a c #FFFBF0",
"s c gray100",
/* pixels */
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" .OOo. ",
" &uutew% o%%&%. ",
" wsaaaspw. OtuuuuwO ",
" .o OwwwraspO wapuupaeO ",
" .wt& %tapw. rse&&wuar. ",
" otau% .wut& %e% .wap& ",
" &uatO .wut&. . %up& ",
" .. wapwO%. waatw&&. &uu& ",
" .ww. .wpsuuu& tssappur&. .=tpr. ",
" &pu& .&russsssw &putetuau% owppe% ",
" waaw.%rupuupaatO OOooO&uaw OruuwO ",
" waawoeaur&%&up& wat. wau&. ",
" %pst%rpw. Otaw &uu% Otar. ",
" .esawO%. rae. &uu% %uaw ",
" &asu. &ptO .wptO .wwO ",
" .usuO &uu% .&O .&uuw. .. ",
" &pp& %uu& wauwwwruar. ",
" .eae. %uu& tssaaaauwo .OO. ",
" =aaw. %uaw &ttttte&. &paw ",
" .rapw. &ast ..oo. rssu ",
" OuspO Ouaw %tu& ",
" .rauO O%. ",
" ow% ",
" ",
" ",
" ",
" oOXOO ",
" .O@:>;:#X ",
" .O&OOO&O O#:>>@+#@>;% ",
" O&7000091& &1,:O&o .>-X ",
" &<0q0717909# .oO.OOXXX.. .O>5> war @># ",
" .<00wX .X709#. .%%O#&#::>>>>14:$##O$29: OwO .>:O ",
" %0y6.wr X909&&&#&<>7>525252494299252,7,$ X>;% ",
" .*q0.%si. <907<19999929>,7>42>,7,>,9>9>9: O>-# ",
" &808 O. *q9090902915>91,9,424,79>15>2>9# +;-. ",
" .&8q8. $090909099291,5>>9>52>,,9>24>,>># O-,@ ",
" .&000O <9020909399257192>91,7514,4,>4>>>>:$>>>;# ",
" .&000< $00909020909972,4,7,>5>2>,41>>>>>>>>>>>;>O ",
" .&0000*. .$099090909092929>24,7,7,4,7,>5>,>>>>;>;>>;# ",
" #7000q9777090209399020991951,7,7,1,4>>>>4>>4>>>>>;>;;. ",
" O<q000000090909090090909927,7,7,>51,5>5>,>,>>>>;>>>;>@. ",
" O000000090209090920902927,9,>,242>4>,>>>4>>>;4>;>;>;;X ",
" o<000090209093909090999924249>424,,>4>5>,>4>>>>:->;;;@ ",
" .*000000909090920902002729>2>9,>24>9>,>4>>>,>;$#:;>->;X ",
" *900000<1090900909099999>9,7,1541,>>4>,>,5>:+#;>>>;;>@. ",
" &0000007$*7209q909090291251515>2,4,9,,4>:$#@:;>>;;>->-. ",
" #00000900<$***<111937919515>9>7>4>:$$$#$#::>>>>;>>;;;>X. ",
" O000000090917<$*###$*##+$#+##$+#$##$::>>>,>>>;>>;;>;>;@O ",
" O00000000000000000809917141>1>7>129,2524,4>,4>4>>>>>>>$O "
};
#define keropi_xpm_width 64
#define keropi_xpm_height 64
+72
View File
@@ -0,0 +1,72 @@
/* XPM */
static char *keropi_icon[] = {
/* columns rows colors chars-per-pixel */
"32 32 34 1",
" c black",
". c #291800",
"X c #293800",
"o c #291852",
"O c #293852",
"+ c #295900",
"@ c #007952",
"# c #295952",
"$ c #297952",
"% c #523852",
"& c #525952",
"* c #527952",
"= c #7B5952",
"- c #7B7952",
"; c #009E52",
": c #00BE52",
"> c #299E52",
", c #29BE52",
"< c #29DF52",
"1 c #52BE52",
"2 c #52DF52",
"3 c #29BEAD",
"4 c #29DFAD",
"5 c #52BEAD",
"6 c #52DFAD",
"7 c #848684",
"8 c #AD9EAD",
"9 c #A5A6A5",
"0 c #ADBEAD",
"q c #D6BEAD",
"w c #C6DFC6",
"e c #D6DFFF",
"r c #FFFFF7",
"t c gray100",
/* pixels */
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttttttttttttttttttttt",
"tttttttttttttrw87*79wrtttttttttt",
"ttttttttttttw&#@>,:>$*wttrtttttt",
"tttttttrtrtw$>,,@+#@,:&etttttrtt",
"rtrrtttttte71<>O&o .,;-rttrtttt",
"*7***=78wr7,4, 7r9 @,$etrttttt",
",,,13>>**&$26> O7O .,>0tttttrt",
"2363266242<5<$ X,:7ttrtttt",
"32,<5<,<6,6,6> O,;*rttttrt",
"<323<56,14,2,6# +:;&ttttttt",
"6,42,<<6,23,<,,# O;<@7tttrttt",
",61<5413<3<,3,,,,>$,,,:$qttttttt",
"5<,4,2,<31,,,,,,,,,,,:,#rtrtttrt",
"<5<5<3<5<,4,<,,,,:,:,,:#0tttrttt",
"5<5<1<3,,,,3,,3,,,,,:,::#wtttttt",
"<5<,41<4,4,<,<,,,,:,,,:,@&rtttrt",
",<232,3,<,,,3,,,:3,:,:,::X7ttttt",
"6,323<<,3,4,<,3,,,,>;,:::@orrttt",
",6<,23,6,<,3,,,<,:$#>:,;,:X9tttt",
"5<1431<,,3,<,<4,>+#:,,,::,@%ttrt",
"414,2<3<6<<3,>$#@>:,,::,;,;.wttt",
",6,5,3,>$$$#$#>>,,,,:,,:::,X8ttt",
"##$+#$##$>>,,,<,,,:,,::,:,:@7ttt",
",1,5,126<2423<3,<3,3,,,,,,,$&rtt"
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+14
View File
@@ -0,0 +1,14 @@
#define keropi_mono_width 32
#define keropi_mono_height 32
static char keropi_mono_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x0F, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x10, 0x47, 0x00,
0x00, 0x90, 0xDE, 0x00, 0x7F, 0x48, 0x9C, 0x00, 0xC0, 0xC7, 0x3E, 0x01,
0x00, 0xC0, 0x3F, 0x01, 0x00, 0xC0, 0x3F, 0x01, 0x00, 0xC0, 0x3F, 0x01,
0x00, 0x80, 0x9F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x04,
0x00, 0x00, 0x06, 0x08, 0x00, 0xC0, 0x01, 0x08, 0x00, 0x3E, 0x00, 0x08,
0xFF, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, };
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+94
View File
@@ -0,0 +1,94 @@
/* XPM */
static char *motorola[] = {
/* columns rows colors chars-per-pixel */
"41 48 40 1",
" c black",
". c #2A1F00",
"X c #2A3F00",
"o c #2A1F55",
"O c #2A3F55",
"+ c #553F55",
"@ c #555F55",
"# c #7F5F55",
"$ c #7F7F55",
"% c blue",
"& c #2A1FFF",
"* c #2A3FFF",
"= c #2A5FFF",
"- c #2A7FFF",
"; c #553FFF",
": c #7F7FAA",
"> c #555FFF",
", c #557FFF",
"< c #7F7FFF",
"1 c #559FFF",
"2 c #7F9FFF",
"3 c #7FBFFF",
"4 c #808080",
"5 c #A0A0A4",
"6 c #AABFAA",
"7 c #AA9FFF",
"8 c #AABFFF",
"9 c #A6CAF0",
"0 c #AADFFF",
"q c #D4BFAA",
"w c #D4BFFF",
"e c #C0DCC0",
"r c #CCCCFF",
"t c #D4DFFF",
"y c #CCFFFF",
"u c #D4FFFF",
"i c #FFCCFF",
"p c #FFDFFF",
"a c #FFFBF0",
"s c gray100",
/* pixels */
"sssssssssssssssssssssssssssssssssssssssss",
"sssssssssssssssssssst822,==;=,,78tsssssss",
"ssssssssssssssssst2>*%*%*%*%*%&&&,sssssss",
"sssssssssssssst2=*%%**%*&*&%%%**%,sssssss",
"sssssssssssss2*%*%***=11233ssss**1sssssss",
"sssssssssss8>**&*=-2yasassss=209,7sssssss",
"ssssssssss,**%*-8tsssssssass=2satusssssss",
"ssssssss8=&%*,tssssssssssssa=2u*,>tssssss",
"sssssss,&%*3ussssssssssst78t=<r*8*rssssss",
"ssssss8%*-tsssssssssssas2*,2=29*9*8*sssss",
"ssssss=*,assssssssssst22===2=,t&=8*,sssss",
"sssss1%,sssssssssa2<r=%,=9=9=<s2,2u88ssss",
"ssssr%=ssssssssa=8*,,2*r,*=9,=8sasu&=usss",
"ssss,%8ssssssas2%=*8,<*tr=9tasssssu=%8sss",
"ssst&98s==st,<t=*,*8,2*asaassssssss3%>sss",
"sss=*2=a==s8*=2r*8==2t9ssssst8sssssa=*tss",
"ssu*-=*2**2=*8,r*9atasssssss>&9sssss7&9ss",
"ssr%2=%=*%2=*,=t,=ssssssssss=*rr*=ts8&8ss",
"ss3*2*****>9**9sasssssss,<ss=*t>*=3s8*7ss",
"ss2*2*2&2*=satssssssssrs,,s2**2*2=7s8%9ss",
"ss7*,*2*2**usssssssss,*88rr***,**=ts<*yss",
"ss8*,*2*2**as88ttsss<%*2*,,=,*,*222s==sss",
"ss8*22r3t88ss2<,*8=3-*9t&,>3,*2*<&2t%2sss",
"sst*=ssasssss78,%*&>,*rt*,=,**r2=,t,=asss",
"sss2%7sssssss*,1&1=*s2*2*,,&=&tass2%9ssss",
"sssa**tssssss=<2%t2*t3%2*,t83*tsss*=sssss",
"ssss3%>ssssss>,1*t3*3**r=2ssaussu>*tsssss",
"ssssu,%2sssss,<2%tr*=%2sassssss8=%3ssssss",
"ssssst=%,tsss,,t2at*2tssssssst<*%,sssssss",
"ssssssr*%*2ss2,sssssassssssp8=%*1ssssssss",
"sssssss3**%=,rssssssssssp82=%%-rsssssssss",
"sssssssst,=*%*>,228872,==*%*,9sssssssssss",
"sssssssssss8,*%%%%*%%&%*&=8ssssssssssssss",
"ssssssssssssst921-==-,18tssssssssssssssss",
"sssssssssssssssssasssssssssssssssssssssss",
"ssateapeasse5esst6ase5assa6tsse5tsse5asss",
"sss+ 45 5a@ +se.+tao .ta. .ae .e5 Oass",
"ssa. 44 45 465ao es@Oe 54 5.:+.5 @++4 4ss",
"sst. .O @+.sss5 .5a.+ e@os@+ 4s4 .6s.@ss",
"sse @ .++O.assO.eo.OOe 4+Xa+O 4s@ o5ao+ss",
"ss6 [email protected] o45@ 4.OO.4 45 @.5@ 4 @@.4 5ss",
"ssq t$4eos5. @aO .esO Oaa+ +seo Oa6 @ass",
"sssaasaaaasteaaattsaaeaasatassaeassaessss",
"ssssssss8,122<1,,,,=>>,>=,,,,,,,,>,,,ssss",
"sssssssssspsuutttrrr88211<,>==****&%*tsss",
"sssseee6s6pepe5a5eqtaqa5essssssuuut00ssss",
"ssss555+e45ee5#a@e4q54e+5ssssssssssssssss",
"sssatat6p6peie5a5wqet6sqessssssssssssssss"
};
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

+26
View File
@@ -0,0 +1,26 @@
/* XPM */
static char *nekolgc[] = {
/* columns rows colors chars-per-pixel */
"57 17 3 1",
" c black",
". c #808080",
"X c #C0C0C0",
/* pixels */
"X XXX X ",
"X XX. X .XX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
"X XXXX X XXXX X X X X X X X XXXX X X X X X XXX ",
"X XXXX. X .XXXX X X X X XXX . X X XXXX X X XXX . X X XXX ",
"X XXXXX XXXXX X X X X XX X XXXX X X XX X XXX ",
"X X X X X X XXX . X X X X X XXX . X X X ",
"X X X . X XXX X X X XXXX . X XXX X X X XXX ",
"X XXX XXX X X X X X X X XXXX X X X X X XXX ",
"X .X X. X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
"X X ",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
" XX X X X. X X X X XXXX XXXX XXX X XX ",
" X X X X X. X X X X XXXX XXX X X XXXX X XX",
" X X X X . X X X X X X XXX X X X X X XX",
" XX X X X XX XX X X X XXX X X X X X XX",
" XXXX . X X. XXX .XX X XXXX XXX X X X X X XX",
" XXXXX XX X. XXX .XXX XXXXX XX XXX XX XX "
};
+25
View File
@@ -0,0 +1,25 @@
/* XPM */
static char *nulldev[] = {
/* width height ncolors chars_per_pixel */
"16 16 2 1",
/* colors */
" c #9B9B9B",
". c #C0C0C0",
/* pixels */
"................",
"................",
"... ...",
".. .......... ..",
".. . ...... . ..",
".. .. .... .. ..",
".. ... .. ... ..",
".. .... ..... ..",
".. ..... .... ..",
".. ... .. ... ..",
".. .. .... .. ..",
".. . ...... . ..",
".. .......... ..",
"... ...",
"................",
"................"
};
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

+27
View File
@@ -0,0 +1,27 @@
/* XPM */
static char *opm[] = {
/* columns rows colors chars-per-pixel */
"30 18 3 1",
" c black",
". c #808080",
"X c #C0C0C0",
/* pixels */
"XXXXXXXXXXXXXXXXXXXXXXXXXXX X",
" X ",
" XXXXXXXXXXXXXXXXXXXXXXXX . ",
" XX XX .XX .XX X X",
" X XX .XX X X X X X XXXX",
" X XX XX X X X X X XXXX",
" X XX XX XX X X X XXXX",
" XX XXX XXXX X X X XXXX",
" XXXXXXXX .XXXXXXXXX. X XXXX",
" XXXXXXXXXXXXXXXXXXXXXXXX XXXX",
" XXXX",
" XXXXXXXXXXXXXXXXXXXXXXXX XXXX",
" X .. . X XX XXXX",
" X X X X X X XX X X XXXX",
" X .. . . X X X X X XXXX",
" XXXXXXXXXXXXXXXXXXXXXXXX XXXX",
" XXXX",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
};
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+20
View File
@@ -0,0 +1,20 @@
// DOSIO用のファイルタイプ
enum {
FTYPE_NONE = 0, // 自動判別 or PC
FTYPE_SMIL, // システム予約
FTYPE_TEXT, // テキストファイル
FTYPE_BMP, // Bitmap
FTYPE_PICT, // Picture (予約)
FTYPE_PNG, // Png (予約)
FTYPE_WAV, // Wave
FTYPE_D88, // D88
FTYPE_BETA, // ベタイメージ
FTYPE_THD, // .thd ハードディスクイメージ
FTYPE_HDI, // .hdi ハードディスクイメージ
FTYPE_HDD, // .hdd ハードディスクイメージ (予約)
FTYPE_S98, // .s98 ハードディスクイメージ
FTYPE_MIMPI, // mimpi defaultファイル
FTYPE_SRAM // SRAM
};
+650
View File
@@ -0,0 +1,650 @@
/* $Id: dosio.c,v 1.2 2003/12/05 18:07:15 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by NONAKA Kimihiro.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <time.h>
#include "dosio.h"
static char curpath[MAX_PATH+32] = "";
static LPSTR curfilep = curpath;
void
dosio_init(void)
{
/* Nothing to do. */
}
void
dosio_term(void)
{
/* Nothing to do. */
}
/* ファイル操作 */
FILEH
file_open(LPSTR filename)
{
FILEH ret;
ret = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (ret == (FILEH)INVALID_HANDLE_VALUE) {
ret = CreateFile(filename, GENERIC_READ,
0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (ret == (FILEH)INVALID_HANDLE_VALUE)
return (FILEH)FALSE;
}
return ret;
}
FILEH
file_create(LPSTR filename, int ftype)
{
FILEH ret;
(void)ftype;
ret = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ret == (FILEH)INVALID_HANDLE_VALUE)
return (FILEH)FALSE;
return ret;
}
DWORD
file_seek(FILEH handle, long pointer, short mode)
{
return SetFilePointer(handle, pointer, 0, mode);
}
DWORD
file_lread(FILEH handle, void *data, DWORD length)
{
DWORD readsize;
if (ReadFile(handle, data, length, &readsize, NULL) == 0)
return 0;
return readsize;
}
DWORD
file_lwrite(FILEH handle, void *data, DWORD length)
{
DWORD writesize;
if (WriteFile(handle, data, length, &writesize, NULL) == 0)
return 0;
return writesize;
}
WORD
file_read(FILEH handle, void *data, WORD length)
{
DWORD readsize;
if (ReadFile(handle, data, length, &readsize, NULL) == 0)
return 0;
return (WORD)readsize;
}
DWORD
file_zeroclr(FILEH handle, DWORD length)
{
char buf[256];
DWORD size;
DWORD wsize;
DWORD ret = 0;
memset(buf, 0, sizeof(buf));
while (length > 0) {
wsize = (length >= sizeof(buf)) ? sizeof(buf) : length;
size = file_lwrite(handle, buf, wsize);
if (size == (DWORD)-1)
return -1;
ret += size;
if (size != wsize)
break;
length -= wsize;
}
return ret;
}
WORD
file_write(FILEH handle, void *data, WORD length)
{
DWORD writesize;
if (WriteFile(handle, data, length, &writesize, NULL) == 0)
return 0;
return (WORD)writesize;
}
WORD
file_lineread(FILEH handle, void *data, WORD length)
{
LPSTR p = (LPSTR)data;
DWORD readsize;
DWORD pos;
WORD ret = 0;
if ((length == 0) || ((pos = file_seek(handle, 0, 1)) == (DWORD)-1))
return 0;
ZeroMemory(data, length);
if (ReadFile(handle, data, length-1, &readsize, NULL) == 0)
return 0;
while (*p) {
ret++;
pos++;
if ((*p == 0x0d) || (*p == 0x0a)) {
break;
}
p++;
}
*p = '\0';
file_seek(handle, pos, 0);
return ret;
}
short
file_close(FILEH handle)
{
CloseHandle(handle);
return 0;
}
short
file_attr(LPSTR filename)
{
return (short)GetFileAttributes(filename);
}
// カレントファイル操作
void
file_setcd(LPSTR exename)
{
strncpy(curpath, exename, sizeof(curpath));
plusyen(curpath, sizeof(curpath));
curfilep = curpath + strlen(exename) + 1;
*curfilep = '\0';
}
LPSTR
file_getcd(LPSTR filename)
{
strncpy(curfilep, filename, curfilep - curpath);
return curpath;
}
FILEH
file_open_c(LPSTR filename)
{
strncpy(curfilep, filename, curfilep - curpath);
return file_open(curpath);
}
FILEH
file_create_c(LPSTR filename, int ftype)
{
strncpy(curfilep, filename, curfilep - curpath);
return file_create(curpath, ftype);
}
short
file_attr_c(LPSTR filename)
{
strncpy(curfilep, filename, curfilep - curpath);
return file_attr(curpath);
}
int
file_getftype(LPSTR filename)
{
(void)filename;
return FTYPE_NONE;
}
LPSTR
getFileName(LPSTR filename)
{
LPSTR p, q;
for (p = q = filename; *p != '\0'; p++)
if (*p == '/')
q = p + 1;
return q;
}
void
cutFileName(LPSTR filename)
{
LPSTR p, q;
for (p = filename, q = NULL; *p != '\0'; p++)
if (*p == '/')
q = p + 1;
if (q != NULL)
*q = '\0';
}
LPSTR
getExtName(LPSTR filename)
{
LPSTR p;
LPSTR q;
p = getFileName(filename);
q = NULL;
while (*p != '\0') {
if (*p == '.')
q = p + 1;
p++;
}
if (q == NULL)
q = p;
return q;
}
void
cutExtName(LPSTR filename)
{
LPSTR p;
LPSTR q;
p = getFileName(filename);
q = NULL;
while (*p != '\0') {
if (*p == '.')
q = p;
p++;
}
if (q != NULL)
*q = '\0';
}
int
kanji1st(LPSTR str, int pos)
{
int ret = 0;
BYTE c;
for (; pos > 0; pos--) {
c = (BYTE)str[pos];
if (!((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xfc)))
break;
ret ^= 1;
}
return ret;
}
int
kanji2nd(LPSTR str, int pos)
{
int ret = 0;
BYTE c;
while (pos-- > 0) {
c = (BYTE)str[pos];
if (!((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xfc)))
break;
ret ^= 1;
}
return ret;
}
int
ex_a2i(LPSTR str, int min, int max)
{
int ret = 0;
char c;
if (str == NULL)
return(min);
for (;;) {
c = *str++;
if (c == ' ')
continue;
if ((c < '0') || (c > '9'))
break;
ret = ret * 10 + (c - '0');
}
if (ret < min)
return min;
else if (ret > max)
return max;
return ret;
}
void
cutyen(LPSTR str)
{
int pos = strlen(str) - 1;
if ((pos > 0) && (str[pos] == '/'))
str[pos] = '\0';
}
void
plusyen(LPSTR str, int len)
{
int pos = strlen(str);
if (pos) {
if (str[pos-1] == '/')
return;
}
if ((pos + 2) >= len)
return;
str[pos++] = '/';
str[pos] = '\0';
}
void
fname_mix(LPSTR str, LPSTR mix, int size)
{
LPSTR p;
int len;
char c;
char check;
cutFileName(str);
if (mix[0] == '/')
str[0] = '\0';
len = strlen(str);
p = str + len;
check = '.';
while (len < size) {
c = *mix++;
if (c == '\0')
break;
if (c == check) {
/* current dir */
if (mix[0] == '/') {
mix++;
continue;
}
/* parent dir */
if (mix[0] == '.' && mix[1] == '/') {
mix += 2;
cutyen(str);
cutFileName(str);
len = strlen(str);
p = str + len;
continue;
}
}
if (c == '/')
check = '.';
else
check = 0;
*p++ = c;
len++;
}
if (p < str + len)
*p = '\0';
else
str[len - 1] = '\0';
}
/*
* UNIX -> DOS 日時変換
*/
/* $NetBSD: msdosfs_conv.c,v 1.29 2001/01/18 20:28:27 jdolecek Exp $ */
/*-
* Copyright (C) 1995, 1997 Wolfgang Solfrank.
* Copyright (C) 1995, 1997 TooLs GmbH.
* All rights reserved.
* Original code by Paul Popelka ([email protected]) (see below).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Written by Paul Popelka ([email protected])
*
* You can do anything you want with this software, just don't say you wrote
* it, and don't remove this notice.
*
* This software is provided "as is".
*
* The author supplies this software to be publicly redistributed on the
* understanding that the author is not responsible for the correct
* functioning of this software in any circumstances and is not liable for
* any damages caused by this software.
*
* October 1992
*/
/*
* Days in each month in a regular year.
*/
unsigned short const regyear[] = {
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
/*
* Days in each month in a leap year.
*/
unsigned short const leapyear[] = {
31, 29, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
/*
* Variables used to remember parts of the last time conversion. Maybe we
* can avoid a full conversion.
*/
static time_t lasttime;
static unsigned long lastday;
static unsigned short lastddate;
static unsigned short lastdtime;
/*
* Convert the unix version of time to dos's idea of time to be used in
* file timestamps. The passed in unix time is assumed to be in GMT.
*/
void
unix2dostime(time_t t, unsigned short *ddp, unsigned short *dtp, unsigned char *dhp)
{
time_t tt;
unsigned long days;
unsigned long inc;
unsigned long year;
unsigned long month;
const unsigned short *months;
/*
* If the time from the last conversion is the same as now, then
* skip the computations and use the saved result.
*/
tt = t;
t &= ~1;
if (lasttime != t) {
lasttime = t;
lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
+ (((t / 60) % 60) << DT_MINUTES_SHIFT)
+ (((t / 3600) % 24) << DT_HOURS_SHIFT);
/*
* If the number of days since 1970 is the same as the last
* time we did the computation then skip all this leap year
* and month stuff.
*/
days = t / (24 * 60 * 60);
if (days != lastday) {
lastday = days;
for (year = 1970;; year++) {
inc = year & 0x03 ? 365 : 366;
if (days < inc)
break;
days -= inc;
}
months = year & 0x03 ? regyear : leapyear;
for (month = 0; month < 12; month++) {
if (days < months[month])
break;
days -= months[month];
}
lastddate = ((days + 1) << DD_DAY_SHIFT)
+ ((month + 1) << DD_MONTH_SHIFT);
/*
* Remember dos's idea of time is relative to 1980.
* unix's is relative to 1970. If somehow we get a
* time before 1980 then don't give totally crazy
* results.
*/
if (year > 1980)
lastddate += (year - 1980) << DD_YEAR_SHIFT;
}
}
if (dtp)
*dtp = lastdtime;
if (dhp)
*dhp = (tt & 1) * 100;
*ddp = lastddate;
}
/*
* The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
* interval there were 8 regular years and 2 leap years.
*/
#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
static unsigned short lastdosdate;
static unsigned long lastseconds;
/*
* Convert from dos' idea of time to unix'. This will probably only be
* called from the stat(), and fstat() system calls and so probably need
* not be too efficient.
*/
void
dos2unixtime(unsigned int dd, unsigned int dt, unsigned int dh, time_t *tp)
{
unsigned long seconds;
unsigned long m, month;
unsigned long y, year;
unsigned long days;
const unsigned short *months;
if (dd == 0) {
/*
* Uninitialized field, return the epoch.
*/
tp = 0;
return;
}
seconds = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2
+ ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
+ ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
+ dh / 100;
/*
* If the year, month, and day from the last conversion are the
* same then use the saved value.
*/
if (lastdosdate != dd) {
lastdosdate = dd;
days = 0;
year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
for (y = 0; y < year; y++)
days += y & 0x03 ? 365 : 366;
months = year & 0x03 ? regyear : leapyear;
/*
* Prevent going from 0 to 0xffffffff in the following
* loop.
*/
month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
if (month == 0) {
printf("dos2unixtime(): month value out of range (%ld)\n",
month);
month = 1;
}
for (m = 0; m < month - 1; m++)
days += months[m];
days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
}
*tp = seconds + lastseconds;
}
+169
View File
@@ -0,0 +1,169 @@
/* $Id: dosio.h,v 1.1.1.1 2003/04/28 18:06:55 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by NONAKA Kimihiro.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NP2_DOSIO_H__
#define __NP2_DOSIO_H__
#include "common.h"
#include "appftype.h"
#define FILEH HANDLE
#define FSEEK_SET 0
#define FSEEK_CUR 1
#define FSEEK_END 2
#ifdef __cplusplus
extern "C" {
#endif
// DOSIO:関数の準備
void dosio_init(void);
void dosio_term(void);
// ファイル操作
FILEH file_open(LPSTR filename);
FILEH file_create(LPSTR filename, int ftype);
DWORD file_seek(FILEH handle, long pointer, short mode);
DWORD file_lread(FILEH handle, void *data, DWORD length);
DWORD file_lwrite(FILEH handle, void *data, DWORD length);
WORD file_read(FILEH handle, void *data, WORD length);
WORD file_write(FILEH handle, void *data, WORD length);
DWORD file_zeroclr(FILEH handle, DWORD length);
WORD file_lineread(FILEH handle, void *data, WORD length);
short file_close(FILEH handle);
short file_attr(LPSTR filename);
// カレントファイル操作
void file_setcd(LPSTR exename);
LPSTR file_getcd(LPSTR filename);
FILEH file_open_c(LPSTR filename);
FILEH file_create_c(LPSTR filename, int ftype);
short file_attr_c(LPSTR filename);
int file_getftype(LPSTR filename);
// 日時の取得
void dosdateset(BYTE *dat);
void dostimeset(BYTE *dat);
LPSTR getFileName(LPSTR filename);
void cutFileName(LPSTR filename);
LPSTR getExtName(LPSTR filename);
void cutExtName(LPSTR filename);
void plusyen(LPSTR str, int len);
void cutyen(LPSTR str);
int kanji1st(LPSTR str, int pos);
int ex_a2i(LPSTR str, int min, int max);
void fname_mix(LPSTR str, LPSTR mix, int size);
/* $NetBSD: direntry.h,v 1.14 1997/11/17 15:36:32 ws Exp $ */
/*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
* Copyright (C) 1994, 1995, 1997 TooLs GmbH.
* All rights reserved.
* Original code by Paul Popelka ([email protected]) (see below).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Written by Paul Popelka ([email protected])
*
* You can do anything you want with this software, just don't say you wrote
* it, and don't remove this notice.
*
* This software is provided "as is".
*
* The author supplies this software to be publicly redistributed on the
* understanding that the author is not responsible for the correct
* functioning of this software in any circumstances and is not liable for
* any damages caused by this software.
*
* October 1992
*/
/*
* This is the format of the contents of the deTime field in the direntry
* structure.
* We don't use bitfields because we don't know how compilers for
* arbitrary machines will lay them out.
*/
#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
#define DT_2SECONDS_SHIFT 0
#define DT_MINUTES_MASK 0x7E0 /* minutes */
#define DT_MINUTES_SHIFT 5
#define DT_HOURS_MASK 0xF800 /* hours */
#define DT_HOURS_SHIFT 11
/*
* This is the format of the contents of the deDate field in the direntry
* structure.
*/
#define DD_DAY_MASK 0x1F /* day of month */
#define DD_DAY_SHIFT 0
#define DD_MONTH_MASK 0x1E0 /* month */
#define DD_MONTH_SHIFT 5
#define DD_YEAR_MASK 0xFE00 /* year - 1980 */
#define DD_YEAR_SHIFT 9
void unix2dostime(time_t t, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp);
void dos2unixtime(u_int dd, u_int dt, u_int dh, time_t *tp);
#ifdef __cplusplus
};
#endif
#endif /* __NP2_DOSIO_H__ */
+295
View File
@@ -0,0 +1,295 @@
/* $Id: fake.c,v 1.2 2003/12/05 18:07:15 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by NONAKA Kimihiro.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include "windows.h"
#include "mmsystem.h"
int WINAPI
MessageBox(HWND hWnd, LPCSTR str, LPCSTR title, UINT flags)
{
(void)hWnd;
(void)flags;
printf("----- %s\n", title);
printf("%s\n", str);
printf("-----\n\n");
return 0;
}
void WINAPI
PostQuitMessage(int m)
{
exit(m);
}
DWORD WINAPI
GetLastError(VOID)
{
return NO_ERROR;
}
BOOL WINAPI
SetEndOfFile(HANDLE hFile)
{
(void)hFile;
return FALSE;
}
WINMMAPI MMRESULT WINAPI
midiOutPrepareHeader(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh)
{
(void)hmo;
(void)pmh;
(void)cbmh;
return !MIDIERR_STILLPLAYING; // (¤©
}
WINMMAPI MMRESULT WINAPI
midiOutUnprepareHeader(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh)
{
(void)hmo;
(void)pmh;
(void)cbmh;
return MMSYSERR_NOERROR;
}
WINMMAPI MMRESULT WINAPI
midiOutShortMsg(HMIDIOUT hmo, DWORD dwMsg)
{
(void)hmo;
(void)dwMsg;
return MMSYSERR_NOERROR;
}
WINMMAPI MMRESULT WINAPI
midiOutLongMsg(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh)
{
(void)hmo;
(void)pmh;
(void)cbmh;
return MMSYSERR_NOERROR;
}
WINMMAPI MMRESULT WINAPI
midiOutOpen(LPHMIDIOUT phmo, UINT uDeviceID, DWORD dwCallback,
DWORD dwInstance, DWORD fdwOpen)
{
(void)phmo;
(void)uDeviceID;
(void)dwCallback;
(void)dwInstance;
(void)fdwOpen;
return !MMSYSERR_NOERROR; // (¤£
}
WINMMAPI MMRESULT WINAPI
midiOutClose(HMIDIOUT hmo)
{
(void)hmo;
return MMSYSERR_NOERROR;
}
WINMMAPI MMRESULT WINAPI
midiOutReset(HMIDIOUT hmo)
{
(void)hmo;
return MMSYSERR_NOERROR;
}
static int _WritePrivateProfileString_subr(
FILE *, long, long, LPCSTR, LPCSTR);
BOOL WINAPI
WritePrivateProfileString(LPCSTR sect, LPCSTR key, LPCSTR str, LPCSTR inifile)
{
char lbuf[256];
char newbuf[256];
struct stat sb;
FILE *fp;
long pos;
int found = 0;
int notfound = 0;
int delta;
if (stat(inifile, &sb) == 0)
fp = fopen(inifile, "r+");
else
fp = fopen(inifile, "w+");
if (!fp)
return FALSE;
while (!feof(fp)) {
fgets(lbuf, sizeof(lbuf), fp);
/* XXX should be case insensitive */
if (lbuf[0] == '['
&& !strncasecmp(sect, &lbuf[1], strlen(sect))
&& lbuf[strlen(sect) + 1] == ']') {
found = 1;
break;
}
}
if (feof(fp) && !found) {
/*
* Now create new section and key.
*/
rewind(fp);
snprintf(newbuf, sizeof(newbuf), "[%s]\n", sect);
if (fwrite(newbuf, strlen(newbuf), 1, fp) < 1)
goto writefail;
snprintf(newbuf, sizeof(newbuf), "%s=%s\n", key, str);
if (fwrite(newbuf, strlen(newbuf), 1, fp) < 1)
goto writefail;
fclose(fp);
return TRUE;
}
pos = 0; /* gcc happy */
found = 0;
while (!feof(fp)) {
pos = ftell(fp);
fgets(lbuf, sizeof(lbuf), fp);
if (lbuf[0] == '[' && strchr(lbuf, ']')) {
notfound = 1;
break;
}
/* XXX should be case insensitive */
if (!strncasecmp(key, lbuf, strlen(key))
&& lbuf[strlen(key)] == '=') {
found = 1;
snprintf(newbuf, sizeof(newbuf), "%s=%s\n", key, str);
delta = strlen(newbuf) - strlen(lbuf);
if (delta == 0) {
if (!strncasecmp(newbuf, lbuf, strlen(newbuf)))
break;
/* overwrite */
fseek(fp, pos, SEEK_SET);
if (fwrite(newbuf, strlen(newbuf), 1, fp) < 1)
goto writefail;
} else if (delta > 0) {
if (!_WritePrivateProfileString_subr(fp, pos,
ftell(fp), newbuf, inifile))
goto writefail;
} else {
if (!_WritePrivateProfileString_subr(fp, pos,
ftell(fp), newbuf, inifile))
goto writefail;
}
break;
}
}
if (feof(fp) && !found) {
/*
* Now create new key.
*/
fseek(fp, 0L, SEEK_END);
snprintf(newbuf, sizeof(newbuf), "%s=%s\n", key, str);
if (fwrite(newbuf, strlen(newbuf), 1, fp) < 1)
goto writefail;
}
else if (notfound) {
snprintf(newbuf, sizeof(newbuf), "%s=%s\n", key, str);
if (!_WritePrivateProfileString_subr(fp, pos,
ftell(fp), newbuf, inifile))
goto writefail;
}
fclose(fp);
return TRUE;
writefail:
fclose(fp);
return FALSE;
}
/*
* XXX: REWRITE ME!!!
*/
static int
_WritePrivateProfileString_subr(FILE *fp, long pos, long nowpos,
LPCSTR buf, LPCSTR file)
{
struct stat sb;
char *p;
if (stat(file, &sb) < 0)
return 1;
p = (char *)malloc(sb.st_size);
if (!p)
return 1;
rewind(fp);
if (fread(p, sb.st_size, 1, fp) < 1)
goto out;
fclose(fp);
fp = fopen(file, "w+");
if (fp == NULL)
goto out;
if (fwrite(p, pos, 1, fp) < 1)
goto out;
if (fwrite(buf, strlen(buf), 1, fp) < 1)
goto out;
if (sb.st_size - nowpos > 0)
if (fwrite(p + nowpos, sb.st_size - nowpos, 1, fp) < 1)
goto out;
free(p);
return 0;
out:
free(p);
return 1;
}
+50
View File
@@ -0,0 +1,50 @@
/* $Id: mmsystem.h,v 1.1.1.1 2003/04/28 18:06:55 nonaka Exp $ */
#ifndef MMSYSTEM_H__
#define MMSYSTEM_H__
#include "windows.h"
#define WINMMAPI
typedef UINT MMRESULT;
typedef HANDLE HMIDIOUT;
typedef HMIDIOUT * LPHMIDIOUT;
typedef struct midihdr {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
struct midihdr * lpNext;
DWORD reserved;
DWORD dwOffset;
DWORD dwReserved[8];
} MIDIHDR, *PMIDIHDR, *NPMIDIHDR, *LPMIDIHDR;
#define MMSYSERR_NOERROR 0
#define MIDIERR_STILLPLAYING 2
#define MIDI_MAPPER -1
#define CALLBACK_NULL 0x00000000L
#ifdef __cplusplus
extern "C" {
#endif
WINMMAPI MMRESULT WINAPI midiOutPrepareHeader(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh);
WINMMAPI MMRESULT WINAPI midiOutUnprepareHeader(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh);
WINMMAPI MMRESULT WINAPI midiOutShortMsg(HMIDIOUT hmo, DWORD dwMsg);
WINMMAPI MMRESULT WINAPI midiOutLongMsg(HMIDIOUT hmo, LPMIDIHDR pmh, UINT cbmh);
WINMMAPI MMRESULT WINAPI midiOutOpen(LPHMIDIOUT phmo, UINT uDeviceID, DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen);
WINMMAPI MMRESULT WINAPI midiOutClose(HMIDIOUT hmo);
WINMMAPI MMRESULT WINAPI midiOutReset(HMIDIOUT hmo);
#ifdef __cplusplus
};
#endif
#endif /* MMSYSTEM_H__ */
+456
View File
@@ -0,0 +1,456 @@
/* $Id: peace.c,v 1.4 2008/11/17 12:24:18 nonaka Exp $ */
/*
* Copyright 2000 Masaru OKI
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "windows.h"
/*-----
*
* From PEACE - http://chiharu.hauN.org/peace/ja/
*
*/
enum {
HTYPE_MEMORY = 0x100,
HTYPE_HEAP,
HTYPE_PROCESS,
HTYPE_THREAD,
HTYPE_MODULE,
HTYPE_FILE,
HTYPE_FILEMAPPING,
HTYPE_SEMAPHORE,
HTYPE_MUTEX,
HTYPE_EVENT,
HTYPE_HWND,
HTYPE_MENU,
#if 0
HTYPE_HDC,
HTYPE_BMP,
HTYPE_ICON,
HTYPE_FONT,
HTYPE_PALETTE,
HTYPE_PEN,
HTYPE_BRUSH,
HTYPE_RGN,
HTYPE_METAFILE,
#endif
HTYPE_CONSOLE,
HTYPE_KEY,
};
struct internal_handle {
void *p;
u_int flags;
size_t psize;
u_int refcount;
int type;
};
struct internal_file {
int fd;
};
#define ptrtohandle(h) \
((struct internal_handle *)((void *)(h) - sizeof(struct internal_handle)))
#define isfixed(h) \
((ptrtohandle(h)->p == (h)) ? 1 : 0)
#define sethandletype(h,t) \
do { \
if (isfixed(h)) \
ptrtohandle(h)->type = (t); \
else \
(((struct internal_handle *)(h))->type = (t)); \
} while (/* CONSTCOND */0)
#define handletype(h) \
((isfixed(h)) ? \
ptrtohandle(h)->type : (((struct internal_handle *)(h))->type))
#ifdef DEBUG
#define DPRF(arg) printf arg
#else /* !DEBUG */
#define DPRF(arg)
#endif /* DEBUG */
DWORD WINAPI
GetTickCount(void)
{
struct timeval tv;
gettimeofday(&tv, 0);
return tv.tv_usec / 1000 + tv.tv_sec * 1000;
}
BOOL WINAPI
ReadFile(HANDLE h, PVOID buf, DWORD len, PDWORD lp, LPOVERLAPPED lpov)
{
struct internal_file *fp;
(void)lpov;
if (h == (HANDLE)INVALID_HANDLE_VALUE)
return FALSE;
fp = LocalLock(h);
*lp = read(fp->fd, buf, len);
LocalUnlock(h);
if (*lp <= 0)
return FALSE;
return TRUE;
}
BOOL WINAPI
WriteFile(HANDLE h, PCVOID buf, DWORD len, PDWORD lp, LPOVERLAPPED lpov)
{
struct internal_file *fp;
(void)lpov;
if (h == (HANDLE)INVALID_HANDLE_VALUE)
return FALSE;
fp = LocalLock(h);
*lp = write(fp->fd, buf, len);
LocalUnlock(h);
if (*lp <= 0)
return FALSE;
return TRUE;
}
HANDLE WINAPI
CreateFile(LPCSTR filename, DWORD rdwr, DWORD share,
LPSECURITY_ATTRIBUTES sap,
DWORD crmode, DWORD flags, HANDLE template)
{
struct internal_file *fp;
HANDLE h;
int fd, fmode = 0;
(void)share;
(void)sap;
(void)flags;
(void)template;
switch (rdwr & (GENERIC_READ|GENERIC_WRITE)) {
case GENERIC_READ:
fmode |= O_RDONLY;
break;
case GENERIC_WRITE:
fmode |= O_WRONLY;
break;
case GENERIC_READ|GENERIC_WRITE:
fmode |= O_RDWR;
default:
break;
}
switch (crmode) {
case CREATE_ALWAYS:
fmode |= O_CREAT;
break;
case OPEN_EXISTING:
break;
}
fd = open(filename, fmode, 0644);
if (fd < 0)
return (HANDLE)INVALID_HANDLE_VALUE;
h = LocalAlloc(0, sizeof(struct internal_file));
sethandletype(h, HTYPE_FILE);
fp = LocalLock(h);
fp->fd = fd;
LocalUnlock(h);
return h;
}
DWORD WINAPI
SetFilePointer(HANDLE h, LONG pos, PLONG newposh, DWORD whence)
{
struct internal_file *fp;
off_t newpos;
int fd;
(void)newposh;
fp = LocalLock(h);
fd = fp->fd;
LocalUnlock(h);
newpos = lseek(fd, pos, whence);
return newpos;
}
BOOL WINAPI
CloseHandle(HANDLE h)
{
switch (handletype(h)) {
case HTYPE_FILE:
{
struct internal_file *fp;
fp = LocalLock(h);
close(fp->fd);
LocalUnlock(h);
}
break;
default:
return FALSE;
}
LocalFree(h);
return TRUE;
}
DWORD WINAPI
GetFileAttributes(LPCSTR path)
{
struct stat sb;
DWORD attr = FILE_ATTRIBUTE_NORMAL;
if (stat(path, &sb) == 0) {
if (S_ISDIR(sb.st_mode))
return FILE_ATTRIBUTE_DIRECTORY;
if (!(sb.st_mode & S_IWUSR))
attr |= FILE_ATTRIBUTE_READONLY;
return attr;
}
return -1;
}
HLOCAL WINAPI
LocalAlloc(UINT flags, UINT bytes)
{
return GlobalAlloc(flags, bytes);
}
HLOCAL WINAPI
LocalFree(HLOCAL h)
{
return GlobalFree(h);
}
PVOID WINAPI
LocalLock(HLOCAL h)
{
return GlobalLock(h);
}
BOOL WINAPI
LocalUnlock(HLOCAL h)
{
return GlobalUnlock(h);
}
HGLOBAL WINAPI
GlobalAlloc(UINT flags, DWORD bytes)
{
struct internal_handle *p;
(void)flags;
p = malloc(bytes + sizeof(struct internal_handle));
if (p != 0) {
p->p = &p[1];
p->psize = bytes;
p->refcount = 0;
p->type = HTYPE_MEMORY;
return p;
}
return 0;
}
HGLOBAL WINAPI
GlobalFree(HGLOBAL h)
{
struct internal_handle *ih = h;
if (h == 0)
return 0;
if (!isfixed(h)) {
free(ih);
return 0;
}
ih = GlobalHandle(h);
if (ih->p == &ih[1]) {
free(ih);
return 0;
}
return h;
}
HGLOBAL WINAPI
GlobalHandle(PCVOID p)
{
return (HGLOBAL)(p - sizeof(struct internal_handle));
}
LPVOID WINAPI
GlobalLock(HGLOBAL h)
{
struct internal_handle *ih = h;
if (isfixed(h))
return h;
ih->refcount++;
return ih->p;
}
BOOL WINAPI
GlobalUnlock(HGLOBAL h)
{
struct internal_handle *ih = h;
if (isfixed(h) || ih->refcount == 0)
return FALSE;
if (--ih->refcount != 0) {
/* still locked */
return TRUE;
}
/* unlocked */
return FALSE;
}
DWORD WINAPI
GetPrivateProfileString(LPCSTR sect, LPCSTR key, LPCSTR defvalue,
LPSTR buf, DWORD len, LPCSTR inifile)
{
char lbuf[256];
FILE *fp;
if (sect == NULL
|| key == NULL
|| defvalue == NULL
|| buf == NULL
|| len == 0
|| inifile == NULL)
return 0;
bzero(buf, len);
fp = fopen(inifile, "r");
if (fp == NULL)
goto nofile;
while (!feof(fp)) {
fgets(lbuf, sizeof(lbuf), fp);
/* XXX should be case insensitive */
if (lbuf[0] == '['
&& !strncasecmp(sect, &lbuf[1], strlen(sect))
&& lbuf[strlen(sect) + 1] == ']')
break;
}
if (feof(fp))
goto notfound;
while (!feof(fp)) {
fgets(lbuf, sizeof(lbuf), fp);
if (lbuf[0] == '[' && strchr(lbuf, ']'))
goto notfound;
/* XXX should be case insensitive */
if (!strncasecmp(key, lbuf, strlen(key))
&& lbuf[strlen(key)] == '=') {
char *dst, *src;
src = &lbuf[strlen(key) + 1];
dst = buf;
while (*src != '\r' && *src != '\n' && *src != '\0')
*dst++ = *src++;
*dst = '\0';
fclose(fp);
return strlen(buf);
}
}
notfound:
DPRF(("[%s]:%s not found\n", sect, key));
fclose(fp);
nofile:
strncpy(buf, defvalue, len);
/* not include nul */
return strlen(buf);
}
UINT WINAPI
GetPrivateProfileInt(LPCSTR sect, LPCSTR key, INT defvalue, LPCSTR inifile)
{
char lbuf[256];
FILE *fp;
if (sect == NULL
|| key == NULL
|| inifile == NULL)
return 0;
fp = fopen(inifile, "r");
if (fp == NULL)
goto nofile;
while (!feof(fp)) {
fgets(lbuf, sizeof(lbuf), fp);
/* XXX should be case insensitive */
if (lbuf[0] == '['
&& !strncasecmp(sect, &lbuf[1], strlen(sect))
&& lbuf[strlen(sect) + 1] == ']')
break;
}
if (feof(fp))
goto notfound;
while (!feof(fp)) {
fgets(lbuf, sizeof(lbuf), fp);
if (lbuf[0] == '[' && strchr(lbuf, ']'))
goto notfound;
/* XXX should be case insensitive */
if (!strncasecmp(key, lbuf, strlen(key))
&& lbuf[strlen(key)] == '=') {
int value;
sscanf(&lbuf[strlen(key) + 1], "%d", &value);
fclose(fp);
return value;
}
}
notfound:
fclose(fp);
nofile:
return defvalue;
}
+39
View File
@@ -0,0 +1,39 @@
/* $Id: peace.h,v 1.1.1.1 2003/04/28 18:06:55 nonaka Exp $ */
#ifndef __NP2_PEACE_H__
#define __NP2_PEACE_H__
#ifdef __cplusplus
extern "C" {
#endif
DWORD WINAPI GetTickCount(void);
BOOL WINAPI ReadFile(HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED);
BOOL WINAPI WriteFile(HANDLE, PCVOID, DWORD, PDWORD, LPOVERLAPPED);
HANDLE WINAPI CreateFile(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES,
DWORD, DWORD, HANDLE);
DWORD WINAPI SetFilePointer(HANDLE, LONG, PLONG, DWORD);
BOOL WINAPI CloseHandle(HANDLE);
DWORD WINAPI GetFileAttributes(LPCSTR);
HLOCAL WINAPI LocalAlloc(UINT, UINT);
HLOCAL WINAPI LocalFree(HLOCAL);
PVOID WINAPI LocalLock(HLOCAL);
BOOL WINAPI LocalUnlock(HLOCAL);
HGLOBAL WINAPI GlobalAlloc(UINT, DWORD);
HGLOBAL WINAPI GlobalFree(HGLOBAL);
LPVOID WINAPI GlobalLock(HGLOBAL);
BOOL WINAPI GlobalUnlock(HGLOBAL);
HGLOBAL WINAPI GlobalHandle(PCVOID);
DWORD WINAPI GetPrivateProfileString(LPCSTR, LPCSTR, LPCSTR, LPSTR,
DWORD, LPCSTR);
UINT WINAPI GetPrivateProfileInt(LPCSTR, LPCSTR, INT, LPCSTR);
#ifdef __cplusplus
};
#endif
#endif /* __NP2_PEACE_H__ */
+211
View File
@@ -0,0 +1,211 @@
/* $Id: windows.h,v 1.1.1.1 2003/04/28 18:06:55 nonaka Exp $ */
#ifndef __NP2_WIN32EMUL_H__
#define __NP2_WIN32EMUL_H__
#include <sys/param.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>
typedef signed char CHAR;
typedef signed short SHORT;
typedef signed int INT;
typedef signed long LONG;
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef unsigned long ULONG;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef int BOOL;
typedef WORD WPARAM;
typedef DWORD LPARAM;
typedef LONG LRESULT;
typedef void VOID;
typedef void *PVOID;
typedef void *LPVOID;
typedef const void *PCVOID;
typedef long *PLONG;
typedef BYTE *LPBYTE;
typedef WORD *LPWORD;
typedef DWORD *PDWORD;
typedef DWORD *LPDWORD;
typedef char *LPSTR;
typedef const char *LPCSTR;
typedef void * LPSECURITY_ATTRIBUTES;
typedef void * LPOVERLAPPED;
typedef int HWND;
typedef void * HANDLE;
typedef HANDLE HLOCAL;
typedef HANDLE HGLOBAL;
typedef void * DRAWITEMSTRUCT;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef MAX_PATH
#define MAX_PATH MAXPATHLEN
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef AVE
#define AVE(a, b) (((a)+(b))/2)
#endif
/*
* DUMMY DEFINITION
*/
#define WINAPI
#define CALLBACK
#define UNUSED(v) ((void)(v))
#ifndef INLINE
#define INLINE static inline
#endif
#define RGB(r,g,b) ((DWORD)((BYTE)(r))|((WORD)((BYTE)(g)))|((DWORD)((BYTE)(b))))
#define MB_APPLMODAL 0
#define MB_ICONSTOP 16
#define MB_ICONINFORMATION 64
#define MB_OK 0
#define GPTR 64
/* for BITMAP */
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
/* for dosio.c */
#define GENERIC_READ 1
#define GENERIC_WRITE 2
#define OPEN_EXISTING 1
#define CREATE_ALWAYS 2
#define CREATE_NEW 3
#define FILE_SHARE_READ 0x00000001
#define FILE_SHARE_WRITE 0x00000002
#define FILE_SHARE_DELETE 0x00000004
#define FILE_ATTRIBUTE_READONLY 0x01
#define FILE_ATTRIBUTE_HIDDEN 0x02
#define FILE_ATTRIBUTE_SYSTEM 0x04
#define FILE_ATTRIBUTE_VOLUME 0x08
#define FILE_ATTRIBUTE_DIRECTORY 0x10
#define FILE_ATTRIBUTE_ARCHIVE 0x20
#define FILE_ATTRIBUTE_NORMAL 0x40
#define INVALID_HANDLE_VALUE (HANDLE)-1
#define NO_ERROR 0
#define ERROR_FILE_NOT_FOUND 2
#define ERROR_SHARING_VIOLATION 32
#define FILE_BEGIN 0
#define FILE_CURRENT 1
#define FILE_END 2
/*
* replace
*/
#define wsprintf sprintf
#define ZeroMemory(d,n) memset(d,0,n)
#define CopyMemory(d,s,n) memcpy(d,s,n)
#define timeGetTime() GetTickCount()
/*
* WIN32 structure
*/
typedef struct {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__ ((packed)) BITMAPFILEHEADER;
typedef struct {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__ ((packed)) BITMAPINFOHEADER;
typedef struct {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} __attribute__ ((packed)) RGBQUAD;
typedef struct {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} __attribute__ ((packed)) BITMAPINFO;
typedef struct {
DWORD top;
DWORD left;
DWORD bottom;
DWORD right;
} RECT;
typedef struct {
WORD x;
WORD y;
} POINT;
/*
* prototype
*/
#ifdef __cplusplus
extern "C" {
#endif
int WINAPI MessageBox(HWND, LPCSTR, LPCSTR, UINT);
void WINAPI PostQuitMessage(int);
BOOL WINAPI WritePrivateProfileString(LPCSTR, LPCSTR, LPCSTR, LPCSTR);
DWORD WINAPI GetLastError(VOID);
BOOL WINAPI SetEndOfFile(HANDLE hFile);
#ifdef __cplusplus
};
#endif
#include "peace.h"
#endif /* __NP2_WIN32EMUL_H__ */
+152
View File
@@ -0,0 +1,152 @@
/* $Id: about.c,v 1.4 2008/11/08 02:24:18 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "windows.h"
#include "winx68k.h"
#include "about.h"
#include "version.h"
#include "../icons/adpcm.xpm"
#include "../icons/keropi_icon.xpm"
#include "../icons/motorola.xpm"
#include "../icons/nekolgc.xpm"
#include "../icons/opm.xpm"
static void
dialog_destroy(GtkWidget *w, GtkWidget **wp)
{
UNUSED(wp);
gtk_widget_destroy(w);
}
static GtkWidget *
create_pixmap_from_xpm_d(GtkWidget *w, char **xpm)
{
GdkColormap *colormap;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkWidget *newpixmap;
colormap = gtk_widget_get_colormap(w);
pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap,
&mask, NULL, xpm);
newpixmap = gtk_pixmap_new(pixmap, mask);
gdk_pixmap_unref(pixmap);
gdk_bitmap_unref(mask);
gtk_widget_ref(newpixmap);
gtk_object_set_data_full(GTK_OBJECT(w), "pixmap",
newpixmap, (GtkDestroyNotify)gtk_widget_unref);
return newpixmap;
}
void
create_about_dialog(void)
{
GtkWidget *dialog;
GtkWidget *table;
GtkWidget *button;
GtkWidget *frame;
GtkWidget *frame_table;
GtkWidget *label;
GtkWidget *adpcm_pixmap;
GtkWidget *keropi_pixmap;
GtkWidget *motorola_pixmap;
GtkWidget *nekolgc_pixmap;
GtkWidget *opm_pixmap;
dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(dialog), "About Keropi");
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
#if GTK_MAJOR_VERSION > 1
gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
#endif
gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
GTK_SIGNAL_FUNC(dialog_destroy), NULL);
table = gtk_table_new(6, 2, FALSE);
gtk_container_add(GTK_CONTAINER(dialog), table);
button = gtk_button_new_with_label("OK");
gtk_table_attach(GTK_TABLE(table), button, 4, 5, 1, 2,
GTK_FILL|GTK_EXPAND, 0, 0, 0);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(dialog));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
GTK_WIDGET_SET_FLAGS(button, GTK_HAS_DEFAULT);
gtk_widget_grab_default(button);
gtk_widget_show(button);
motorola_pixmap = create_pixmap_from_xpm_d(dialog, motorola);
gtk_table_attach_defaults(GTK_TABLE(table),motorola_pixmap, 0, 1, 1, 2);
gtk_widget_show(motorola_pixmap);
adpcm_pixmap = create_pixmap_from_xpm_d(dialog, adpcm);
gtk_table_attach_defaults(GTK_TABLE(table), adpcm_pixmap, 1, 2, 1, 2);
gtk_widget_show(adpcm_pixmap);
opm_pixmap = create_pixmap_from_xpm_d(dialog, opm);
gtk_table_attach_defaults(GTK_TABLE(table), opm_pixmap, 2, 3, 1, 2);
gtk_widget_show(opm_pixmap);
nekolgc_pixmap = create_pixmap_from_xpm_d(dialog, nekolgc);
gtk_table_attach_defaults(GTK_TABLE(table), nekolgc_pixmap, 3, 4, 1, 2);
gtk_widget_show(nekolgc_pixmap);
frame = gtk_frame_new(NULL);
gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 6, 0, 1);
gtk_widget_show(frame);
frame_table = gtk_table_new(2, 1, FALSE);
gtk_container_add(GTK_CONTAINER(frame), frame_table);
gtk_widget_show(frame_table);
keropi_pixmap = create_pixmap_from_xpm_d(dialog, keropi_icon);
gtk_misc_set_padding(GTK_MISC(keropi_pixmap), 5, 0);
gtk_table_attach_defaults(GTK_TABLE(frame_table),
keropi_pixmap, 0, 1, 0, 1);
gtk_widget_show(keropi_pixmap);
label = gtk_label_new("Keropi for X - " SOURCE_VERSION "\n"
"Modified by NONAKA Kimihiro\n"
"\nKeropi (WinX68k)\n"
"SHARP X680x0 series emulator\n"
"Version " APP_VER_STRING "\n"
"Copyright (C) 2000-02 Kenjo\n"
"\nUsing \"FM Sound Generator\" (C) cisc");
gtk_misc_set_padding(GTK_MISC(label), 5, 0);
gtk_table_attach_defaults(GTK_TABLE(frame_table), label, 1, 2, 0, 1);
gtk_widget_show(label);
gtk_widget_show(table);
gtk_widget_show(dialog);
}
+33
View File
@@ -0,0 +1,33 @@
/* $Id: about.h,v 1.2 2008/11/08 01:42:42 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef about_h__
#define about_h__
void create_about_dialog(void);
#endif /* about_h__ */
+24
View File
@@ -0,0 +1,24 @@
#ifndef CDASPI_H_
#define CDASPI_H_
int CDASPI_Open(void);
void CDASPI_Close(void);
int CDASPI_Wait(void);
int CDASPI_ReadTOC(void* buf);
int CDASPI_Read(long block, BYTE* buf);
int CDASPI_ExecCmd(BYTE *cdb, int cdb_size, BYTE *out_buff, int out_size);
int CDASPI_IsOpen(void);
void CDASPI_EnumCD(void);
void CDASPI_Init(void);
void CDASPI_Cleanup(void);
extern BYTE CDASPI_CDName[8][4];
extern int CDASPI_CDNum;
extern HINSTANCE ASPIDLL;
DWORD (*pSendASPI32Command)(LPSRB);
DWORD (*pGetASPI32SupportInfo)(VOID);
#endif // CDASPI_H_
+11
View File
@@ -0,0 +1,11 @@
#ifndef CDCTRL_H_
#define CDCTRL_H_
int CDCTRL_Open(void);
void CDCTRL_Close(void);
int CDCTRL_Wait(void);
int CDCTRL_ReadTOC(void* buf);
int CDCTRL_Read(long block, BYTE* buf);
int CDCTRL_IsOpen(void);
#endif // CDCTRL_H_
+29
View File
@@ -0,0 +1,29 @@
#ifndef _winx68k_cdrom
#define _winx68k_cdrom
#include "common.h"
typedef struct {
unsigned char reserved;
unsigned char adr;
unsigned char trackno;
unsigned char reserved1;
unsigned char addr[4];
} TOCENTRY;
typedef struct {
unsigned char size[2];
unsigned char first;
unsigned char last;
TOCENTRY track[100];
} TOC;
void CDROM_Init(void);
void CDROM_Cleanup(void);
BYTE FASTCALL CDROM_Read(DWORD adr);
void FASTCALL CDROM_Write(DWORD adr, BYTE data);
extern BYTE CDROM_ASPIChecked;
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef keropi_cmdline_h
#define keropi_cmdline_h
extern char macrofile[MAX_PATH];
void CheckCmdLine(LPSTR s);
void SetCmdLineFD(void);
#endif //keropi_cmdline_h
+21
View File
@@ -0,0 +1,21 @@
// ---------------------------------------------------------------------------------------
// COMMON - 標準ヘッダ群(COMMON.H)とエラーダイアログ表示とか
// ---------------------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#include "sstp.h"
extern HWND hWndMain;
extern const BYTE PrgTitle[];
void Error(const char* s)
{
char title[80];
sprintf(title, "%s エラー\0", PrgTitle);
SSTP_SendMes(SSTPMES_ERROR);
MessageBox(hWndMain, s, title, MB_ICONERROR | MB_OK);
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef winx68k_common_h
#define winx68k_common_h
#include "windows.h"
#include <stdio.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define SUCCESS 0
#define FAILURE 1
#define FASTCALL
#define STDCALL
#define LABEL
#define __stdcall
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef signed char INT8;
typedef signed short INT16;
typedef signed int INT32;
typedef union {
struct {
BYTE l;
BYTE h;
} b;
WORD w;
} PAIR;
#ifdef __cplusplus
extern "C" {
#endif
void Error(const char* s);
#ifdef __cplusplus
}
#endif
#endif //winx68k_common_h
+317
View File
@@ -0,0 +1,317 @@
/* $Id: dswin.c,v 1.3 2010/11/07 14:22:50 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "windows.h"
#include "common.h"
#include "dswin.h"
#include "prop.h"
#include "adpcm.h"
#include "mercury.h"
#include "fmg_wrap.h"
short playing = FALSE;
BYTE pcmbuffer[2*2*48000];
BYTE *pcmbufp = pcmbuffer;
DWORD pcmfreemax = 22050;
DWORD pcmfree = 22050;
DWORD ds_halfbuffer = 22050 * 4;
DWORD ratebase1000 = 22;
DWORD ratebase = 22050;
long DSound_PreCounter = 0;
#ifndef NAUDIOBUFFER
#define NAUDIOBUFFER 3
#endif
int audio_fd = -1;
int audio_nextbuf;
char *audio_event;
char *audio_buffer[NAUDIOBUFFER];
// ????????????
DWORD calc_blocksize(DWORD size);
static void sdlaudio_callback(void *userdata, unsigned char *stream, int len);
static BOOL buffer_init(DWORD rate, DWORD samples);
static void buffer_cleanup(void);
// ---------------------------------------------------------------------------
// ??????
// ---------------------------------------------------------------------------
#ifndef NOSOUND
#include "SDL.h"
#include "SDL_audio.h"
int
DSound_Init(unsigned long rate, unsigned long buflen)
{
SDL_AudioSpec fmt;
DWORD samples;
int rv;
// ??????????????
if (playing) {
return FALSE;
}
// ????????????
if (rate == 0) {
audio_fd = -1;
return TRUE;
}
// pcmfreemax = Dsound??????????????????????????
pcmfree = pcmfreemax = (DWORD)rate * buflen / 200 / 2;
ds_halfbuffer = pcmfreemax * 4;
pcmbufp = pcmbuffer;
ratebase1000 = rate / 1000;
ratebase = rate;
samples = calc_blocksize(pcmfreemax);
audio_nextbuf = 0;
audio_event = 0;
// ??????
rv = SDL_Init(SDL_INIT_AUDIO);
if (rv < 0) {
audio_fd = -1;
return FALSE;
}
// ??????????????????????????????
bzero(&fmt, sizeof(fmt));
fmt.freq = rate;
fmt.format = AUDIO_S16SYS;
fmt.channels = 2;
fmt.samples = samples;
fmt.callback = sdlaudio_callback;
fmt.userdata = (void *)ds_halfbuffer;
audio_fd = SDL_OpenAudio(&fmt, NULL);
if (audio_fd < 0) {
SDL_Quit();
return FALSE;
}
buffer_init(rate, samples);
playing = TRUE;
return TRUE;
}
void
DSound_Play(void)
{
if (audio_fd >= 0)
SDL_PauseAudio(0);
}
void
DSound_Stop(void)
{
if (audio_fd >= 0)
SDL_PauseAudio(1);
}
// ---------------------------------------------------------------------------
// ????????
// ---------------------------------------------------------------------------
int
DSound_Cleanup(void)
{
playing = FALSE;
if (audio_fd >= 0) {
SDL_CloseAudio();
SDL_Quit();
buffer_cleanup();
audio_fd = -1;
}
return TRUE;
}
// ---------------------------------------------------------------------------
// ??????????????
// ---------------------------------------------------------------------------
void FASTCALL
DSound_Send0(long clock)
{
int length = 0;
if (audio_fd >= 0) {
DSound_PreCounter += (ratebase * clock);
while (DSound_PreCounter >= 10000000L) {
length++;
DSound_PreCounter -= 10000000L;
}
if (length) {
if ((long)pcmfree > (long)length) {
ADPCM_Update((short *)pcmbufp, length);
OPM_Update((short *)pcmbufp, length);
#ifndef NO_MERCURY
Mcry_Update((short *)pcmbufp, length);
#endif
pcmbufp += length * sizeof(WORD) * 2;
pcmfree -= length;
} else {
ADPCM_Update((short *)pcmbufp, pcmfree);
OPM_Update((short *)pcmbufp, pcmfree);
#ifndef NO_MERCURY
Mcry_Update((short *)pcmbufp, pcmfree);
#endif
pcmbufp += pcmfree * sizeof(WORD) * 2;
pcmfree = 0;
}
}
}
}
void FASTCALL
DSound_Send(void)
{
short *q;
if (audio_fd >= 0) {
if (audio_event) {
q = (short *)audio_event;
audio_event = 0;
ADPCM_Update((short *)pcmbufp, pcmfree);
OPM_Update((short *)pcmbufp, pcmfree);
#ifndef NO_MERCURY
Mcry_Update((short *)pcmbufp, pcmfree);
#endif
memcpy(q, pcmbuffer, ds_halfbuffer);
// ????????
pcmbufp = pcmbuffer;
pcmfree = pcmfreemax;
}
}
}
static void
sdlaudio_callback(void *userdata, unsigned char *stream, int len)
{
if (audio_event != NULL)
bzero(audio_event, (DWORD)userdata);
SDL_MixAudio(stream, audio_buffer[audio_nextbuf], len,
SDL_MIX_MAXVOLUME);
audio_nextbuf = (audio_nextbuf + 1) % NAUDIOBUFFER;
audio_event = audio_buffer[audio_nextbuf];
}
// ---------------------------------------------------------------------------
// ??????
// ---------------------------------------------------------------------------
DWORD
calc_blocksize(DWORD size)
{
DWORD s = size;
if (size & (size - 1))
for (s = 32; s < size; s <<= 1)
continue;
return s;
}
static BOOL
buffer_init(DWORD rate, DWORD samples)
{
int i;
UNUSED(rate);
for (i = 0; i < NAUDIOBUFFER; i++) {
audio_buffer[i] = (char *)calloc(samples * 4, 1);
if (audio_buffer[i] == NULL) {
fprintf(stderr, "buffer_init: can't alloc memory\n");
return FAILURE;
}
}
return SUCCESS;
}
static void
buffer_cleanup(void)
{
int i;
for (i = 0; i < NAUDIOBUFFER; i++) {
if (audio_buffer[i]) {
free(audio_buffer[i]);
audio_buffer[i] = 0;
}
}
}
#else /* NOSOUND */
int
DSound_Init(unsigned long rate, unsigned long buflen)
{
return FALSE;
}
void
DSound_Play(void)
{
}
void
DSound_Stop(void)
{
}
int
DSound_Cleanup(void)
{
return TRUE;
}
void FASTCALL
DSound_Send0(long clock)
{
}
void FASTCALL
DSound_Send(void)
{
}
#endif /* !NOSOUND */
+22
View File
@@ -0,0 +1,22 @@
/* $Id: dswin.h,v 1.1.1.1 2003/04/28 18:06:56 nonaka Exp $ */
#ifndef dswin_h__
#define dswin_h__
#include "common.h"
int DSound_Init(unsigned long rate, unsigned long length);
int DSound_Cleanup(void);
void DSound_Play(void);
void DSound_Stop(void);
void FASTCALL DSound_Send0(long clock);
void FASTCALL DSound_Send(void);
void DS_SetVolumeOPM(long vol);
void DS_SetVolumeADPCM(long vol);
void DS_SetVolumeMercury(long vol);
extern DWORD ratebase1000;
#endif /* dswin_h__ */
+40
View File
@@ -0,0 +1,40 @@
#ifndef winx68k_fileio_h
#define winx68k_fileio_h
#include "common.h"
#include "dosio.h"
#define FILEH HANDLE
#define FSEEK_SET 0
#define FSEEK_CUR 1
#define FSEEK_END 2
LPSTR getFileName(LPSTR filename);
//#define getFileName GetFileName
FILEH File_Open(BYTE *filename);
FILEH File_Create(BYTE *filename);
DWORD File_Seek(FILEH handle, long pointer, short mode);
DWORD File_Read(FILEH handle, void *data, DWORD length);
DWORD File_Write(FILEH handle, void *data, DWORD length);
short File_Close(FILEH handle);
short File_Attr(BYTE *filename);
#define File_Open file_open
#define File_Create file_create
#define File_Seek file_seek
#define File_Read file_lread
#define File_Write file_lwrite
#define File_Close file_close
#define File_Attr file_attr
void File_SetCurDir(BYTE *exename);
FILEH File_OpenCurDir(BYTE *filename);
FILEH File_CreateCurDir(BYTE *filename);
short File_AttrCurDir(BYTE *filename);
#define File_SetCurDir file_setcd
#define File_OpenCurDir file_open_c
#define File_CreateCurDir file_create_c
#define File_AttrCurDir file_attr_c
#endif
+269
View File
@@ -0,0 +1,269 @@
; for new GOGO-no-coda (1999/09)
; Copyright (C) 1999 shigeo
; modified by Keiichi SAKAI, URURI, Hash
; 99/07/29
; 99/09/06 フラグ追加
; 99/09/07 SSEの処理を別にする
; 99/09/29 Cx586対策
; 99/11/10 Cxrix対策
; int haveUNIT(void);
; 486未満のCPUまたはFPUを搭載していなければ0
; それ以外は次の値の論理和
; PIIIでは丸め誤差を四捨五入モードにする(らしい)
; haveunit.hとの整合性注意
%include "x11/nasm.h"
tFPU equ (1<<0)
tMMX equ (1<<1)
t3DN equ (1<<2)
tSSE equ (1<<3)
tCMOV equ (1<<4)
tE3DN equ (1<<5) ;/* Athlon用 (extend 3D Now!)*/
tEMMX equ (1<<6) ;/* EMMX=E3DNow!_INT=SSE_INT */
tSPC1 equ (1<<16) ;/* 特別なスイッチ */
tSPC2 equ (1<<17) ;/* 用途は決まってない */
tINTEL equ (1<<8)
tAMD equ (1<<9)
tCYRIX equ (1<<10)
tIDT equ (1<<11)
tUNKNOWN equ (1<<15) ;ベンダーが分からない
tFAMILY4 equ (1<<20) ;/* 486 この時ベンダー判定は当てにならない */
tFAMILY5 equ (1<<21) ;/* 586 (P5, P5-MMX, K6, K6-2, K6-III) */
tFAMILY6 equ (1<<22) ;/* 686以降 P-Pro, P-II, P-III, Athlon */
globaldef _haveUNIT
globaldef setPIII_round
globaldef maskFPU_exception
segment_data
segment_code
ACflag equ (1<<18)
IDflag equ (1<<21)
align 16
haveUNIT:
push ebx
push esi
xor esi,esi
call near haveFPU
jnz near .Lexit
or esi,tFPU
pushfd ;flag保存
pushfd
pop eax ;eax=flag
or eax,ACflag ;eax=flag|ACflag
push eax
popfd ;flag=eax
pushfd
pop eax ;eax=flag
popfd ;flag復元
test eax,ACflag ;ACflagは変化したか?
jz near .Lexit
;486以降
pushfd ;flag保存
pushfd
pop eax ;eax=flag
or eax,IDflag ;eax=flag|IDflag
push eax
popfd ;flag=eax
pushfd
pop eax ;eax=flag
popfd ;flag復元
test eax,IDflag
; jz short .Lexit
jnz .L586
%if 1
;Cyrix 486CPU check Cyrix の HP にあったやつ by Hash
xor ax, ax ; clear ax
sahf ; clear flags, bit 1 is always 1 in flags
mov ax, 5
mov bx, 2
div bl ; do an operation that does not change flags
lahf ; get flags
cmp ah, 2 ; check for change in flags
jne .L486intel ; flags changed not Cyrix
or esi,tCYRIX ; TRUE Cyrix CPU
jmp .L486
.L486intel:
or esi,tINTEL
.L486:
or esi,tFAMILY4
jmp .Lexit
%else
; check for Cyrix 486DLC -- based on check routine
; documented in "Cx486SLC/e SMM Programmer's Guide"
xor dx,dx
cmp dx,dx
pushf
pop cx
mov ax,0FFFFh
mov bx,4
div bx
pushf
pop ax
and ax,8D5h
and cx,8D5h
cmp ax,cx
jnz .L486intel
or esi,tCYRIX
jmp .L486
.L486intel:
or esi,tINTEL
.L486:
or esi,tFAMILY4
jmp .Lexit
%endif
.L586:
;cpuid は eax,ebx,ecx,edxを破壊するので注意!!!
xor eax,eax
cpuid
; cmp ecx,"letn"
cmp ecx,"ntel" ;うわ~NASMと反対に配置するんだ
jne .F00
or esi,tINTEL
jmp .F09
.F00:
; cmp ecx,"DMAc"
cmp ecx,"cAMD"
jne .F01
or esi,tAMD
jmp .F09
.F01:
; cmp ecx,"daet"
cmp ecx,"tead"
jne .F02
or esi,tCYRIX
jmp .F09
.F02:
; cmp ecx,"slua"
cmp ecx,"auls"
jne .F03
or esi,tIDT
jmp .F09
.F03:
or esi,tUNKNOWN
jmp .F09
.F09:
mov eax,1
cpuid
cmp ah,4
jne .F10
or esi,tFAMILY4
jmp .Lexit
.F10:
cmp ah,5
jne .F11
or esi,tFAMILY5
jmp .F19
.F11:
cmp ah,6
jne .F12
or esi,tFAMILY6
jmp .F19
.F12:
or esi,tFAMILY6 ; 7以上は6と見なす
.F19:
;for AMD, IDT
mov eax,80000001h
cpuid
test edx,(1 << 31)
jz .F20
or esi,t3DN
.F20:
test edx,(1 << 15) ;CMOVcc
jz .F21
; test edx,(1 << 16) ;FCMOVcc ;K7から変更 by URURI
; jz .F21
or esi,tCMOV
.F21:
test edx,(1 << 30) ;拡張 3D Now!
jz .F22
%ifdef USE_E3DN
or esi,tE3DN
%endif
.F22:
test edx,(1 << 22) ;AMD MMX Ext
jz .F23
or esi,tEMMX
.F23:
;Intel系
mov eax,1
cpuid
test edx,(1 << 23)
jz .F30
or esi,tMMX
.F30:
test edx,(1 << 15) ;CMOVcc and FCMOV if FPU=1
jz .F31
or esi,tCMOV
.F31:
test edx,(1 << 25)
jz short .Lexit
or esi,tEMMX
%ifndef UNAVAILABLE_SSE
or esi,tSSE
%endif
.Lexit:
mov eax,esi
pop esi
pop ebx
ret
; in:none
; out:ZF FPUあり=1, なし=0
; dest:eax
align 16
haveFPU:
mov al,1
fninit
fnstsw ax
cmp al,0
jne short .LhF_exit
sub esp,4
fnstcw word [esp]
mov ax,[esp]
add esp,4
and ax,103Fh
cmp ax,3Fh
.LhF_exit:
ret
setPIII_round:
;P-IIIのSSEを確実に四捨五入モードに
; mov eax,0x1f80 ; default mode
mov eax,0x9f80 ; flush to ZERO mode
push eax
ldmxcsr [esp] ; setup MXCSR
pop eax
ret
; for Win32 Delphi
maskFPU_exception:
push eax
fnstcw word [esp]
and word [esp],0xFFF2
fldcw word [esp]
pop eax
ret
end
+332
View File
@@ -0,0 +1,332 @@
// JOYSTICK.C - ジョイスティックサポート for WinX68k
// DInputの初期化/終了と、ジョイスティックポートチェック
#include "common.h"
#include "prop.h"
#include "joystick.h"
#if 0
LPDIRECTINPUT dinput = NULL;
LPDIRECTINPUTDEVICE2 joy[2] = {NULL, NULL};
#endif
#ifndef MAX_BUTTON
#define MAX_BUTTON 32
#endif
char joyname[2][MAX_PATH];
char joybtnname[2][MAX_BUTTON][MAX_PATH];
BYTE joybtnnum[2] = {0, 0};
//static int joyactive = 0;
BYTE JoyKeyState = 0;
BYTE JoyKeyState0 = 0;
BYTE JoyKeyState1 = 0;
BYTE JoyState0[2] = {0xff, 0xff};
BYTE JoyState1[2] = {0xff, 0xff};
BYTE JoyPortData[2] = {0, 0};
#if 0
BOOL CALLBACK EnumButtonProc(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pv)
{
BYTE j = *(BYTE*)pv;
if (joybtnnum[j]<MAX_BUTTON)
{
strcpy(joybtnname[j][joybtnnum[j]], lpddoi->tszName);
joybtnnum[j]++;
return DIENUM_CONTINUE;
}
else
return DIENUM_STOP;
}
BOOL CALLBACK JoyEnumProc(LPDIDEVICEINSTANCE pdidi, LPVOID pv)
{
GUID *guid = NULL;
LPDIRECTINPUTDEVICE tmpdev = NULL;
guid = (GUID *)pv;
*guid = pdidi->guidInstance;
if (!joy[0])
{
if ((IDirectInput_CreateDevice(dinput, guid, &tmpdev, NULL)) == DI_OK)
{
if ((IDirectInputDevice_QueryInterface(tmpdev, &IID_IDirectInputDevice2, &joy[0])) == DI_OK)
{
IDirectInputDevice_Release(tmpdev);
return DIENUM_CONTINUE;
}
else
{
joy[0] = NULL;
return DIENUM_CONTINUE;
}
}
else
{
joy[0] = NULL;
return DIENUM_CONTINUE;
}
}
if (!joy[1])
{
if ((IDirectInput_CreateDevice(dinput, guid, &tmpdev, NULL)) == DI_OK)
{
if ((IDirectInputDevice_QueryInterface(tmpdev, &IID_IDirectInputDevice2, &joy[1])) == DI_OK)
{
IDirectInputDevice_Release(tmpdev);
return DIENUM_STOP;
}
else
{
joy[1] = NULL;
return DIENUM_CONTINUE;
}
}
else
{
joy[1] = NULL;
return DIENUM_CONTINUE;
}
}
return DIENUM_CONTINUE;
}
#endif
void Joystick_Init(void)
{
#if 0
BYTE jnum;
HRESULT hres;
GUID guid;
DIPROPRANGE diprg;
DIDEVICEINSTANCE dev;
#endif
JoyKeyState0 = 0;
JoyKeyState1 = 0;
JoyState0[0] = 0xff;
JoyState0[1] = 0xff;
JoyState1[0] = 0xff;
JoyState1[1] = 0xff;
JoyPortData[0] = 0;
JoyPortData[1] = 0;
#if 0
if (FAILED(DirectInputCreate(hInst, DIRECTINPUT_VERSION, &dinput, NULL))) {
return;
}
IDirectInput_EnumDevices(dinput, DIDEVTYPE_JOYSTICK,
(LPDIENUMDEVICESCALLBACK)JoyEnumProc,
&guid, DIEDFL_ATTACHEDONLY);
if ((joy[0] != NULL) && (SUCCEEDED(IDirectInputDevice2_SetDataFormat(joy[0], &c_dfDIJoystick))))
{
hres = IDirectInputDevice2_SetCooperativeLevel(joy[0], hWndMain,
DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
if (SUCCEEDED(hres)) {
ZeroMemory(&diprg, sizeof(diprg));
diprg.diph.dwSize = sizeof(diprg);
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
diprg.diph.dwObj = DIJOFS_X;
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.lMin = 0;
diprg.lMax = 255;
IDirectInputDevice2_SetProperty(joy[0], DIPROP_RANGE, &diprg.diph);
diprg.diph.dwObj = DIJOFS_Y;
IDirectInputDevice2_SetProperty(joy[0], DIPROP_RANGE, &diprg.diph);
IDirectInputDevice2_Acquire(joy[0]);
ZeroMemory(&dev, sizeof(DIDEVICEINSTANCE));
dev.dwSize = sizeof(DIDEVICEINSTANCE);
if (IDirectInputDevice2_GetDeviceInfo(joy[0], &dev) == DI_OK)
strcpy(joyname[0], dev.tszProductName);
else
strcpy(joyname[0], "不明なデバイス");
joybtnnum[0] = 0;
jnum = 0;
IDirectInputDevice_EnumObjects(joy[0],
(LPDIENUMDEVICEOBJECTSCALLBACK)EnumButtonProc,
&jnum, DIDFT_BUTTON);
}
}
if ((joy[1] != NULL) && (SUCCEEDED(IDirectInputDevice2_SetDataFormat(joy[1], &c_dfDIJoystick))))
{
hres = IDirectInputDevice2_SetCooperativeLevel(joy[1], hWndMain,
DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
if (SUCCEEDED(hres)) {
ZeroMemory(&diprg, sizeof(diprg));
diprg.diph.dwSize = sizeof(diprg);
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
diprg.diph.dwObj = DIJOFS_X;
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.lMin = 0;
diprg.lMax = 255;
IDirectInputDevice2_SetProperty(joy[1], DIPROP_RANGE, &diprg.diph);
diprg.diph.dwObj = DIJOFS_Y;
IDirectInputDevice2_SetProperty(joy[1], DIPROP_RANGE, &diprg.diph);
IDirectInputDevice2_Acquire(joy[1]);
}
ZeroMemory(&dev, sizeof(DIDEVICEINSTANCE));
dev.dwSize = sizeof(DIDEVICEINSTANCE);
if (IDirectInputDevice2_GetDeviceInfo(joy[1], &dev) == DI_OK)
strcpy(joyname[1], dev.tszProductName);
else
strcpy(joyname[1], "不明なデバイス");
joybtnnum[1] = 0;
jnum = 1;
IDirectInputDevice_EnumObjects(joy[1],
(LPDIENUMDEVICEOBJECTSCALLBACK)EnumButtonProc,
&jnum, DIDFT_BUTTON);
}
#endif
}
void Joystick_Cleanup(void)
{
#if 0
if (joy[0]) IDirectInputDevice2_Release(joy[0]);
if (joy[1]) IDirectInputDevice2_Release(joy[1]);
if (dinput) IDirectInput_Release(dinput);
#endif
}
void Joystick_Activate(UINT wParam)
{
#if 1
(void)wParam;
#else
if (wParam != WA_INACTIVE)
{
if (joy[0]) IDirectInputDevice2_Acquire(joy[0]);
if (joy[1]) IDirectInputDevice2_Acquire(joy[1]);
}
else
{
if (joy[0]) IDirectInputDevice2_Unacquire(joy[0]);
if (joy[1]) IDirectInputDevice2_Unacquire(joy[1]);
}
#endif
}
BYTE FASTCALL Joystick_Read(BYTE num)
{
BYTE joynum = num;
BYTE ret0 = 0xff, ret1 = 0xff, ret;
#if 1
(void)joynum;
(void)ret0;
(void)ret1;
ret = 0xff;
#else
if (Config.JoySwap) joynum ^= 1;
if (joy[num]) {
ret0 = JoyState0[num];
ret1 = JoyState1[num];
}
if (Config.JoyKey)
{
if ((Config.JoyKeyJoy2)&&(num==1))
ret0 ^= JoyKeyState;
else if ((!Config.JoyKeyJoy2)&&(num==0))
ret0 ^= JoyKeyState;
}
ret = ((~JoyPortData[num])&ret0)|(JoyPortData[num]&ret1);
//ret = ret0;
#endif
return ret;
}
void FASTCALL Joystick_Write(BYTE num, BYTE data)
{
if ( (num==0)||(num==1) ) JoyPortData[num] = data;
}
void FASTCALL Joystick_Update(void)
{
#if 0
BYTE ret0, ret1;
HRESULT hres;
DIJOYSTATE state;
int num;
for (num=0; num<2; num++)
{
ret0 = 0xff;
ret1 = 0xff;
if (joy[num])
{
hres = IDirectInputDevice2_Poll(joy[num]);
if (hres!=DI_OK)
{
if (hres == DIERR_INPUTLOST) { // ロストしてたらAquireしてみる(S.J.PAD2)
IDirectInputDevice2_Acquire(joy[num]);
hres = IDirectInputDevice2_Poll(joy[num]);
if (hres!=DI_OK) // それでもダメなら諦める
continue;
}
}
hres = IDirectInputDevice2_GetDeviceState(joy[num], sizeof(DIJOYSTATE), &state);
if (SUCCEEDED(hres))
{
if (state.lX < 32)
ret0 ^= JOY_LEFT;
else if (state.lX >= 224)
ret0 ^= JOY_RIGHT;
if (state.lY < 32)
ret0 ^= JOY_UP;
else if (state.lY >= 224)
ret0 ^= JOY_DOWN;
if (Config.JOY_BTN[num][0]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][0]] & 0x80)
ret0 ^= JOY_TRG1;
if (Config.JOY_BTN[num][1]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][1]] & 0x80)
ret0 ^= JOY_TRG2;
if (Config.JOY_BTN[num][2]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][2]] & 0x80)
ret1 ^= JOY_TRG3;
if (Config.JOY_BTN[num][3]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][3]] & 0x80)
ret1 ^= JOY_TRG4;
if (Config.JOY_BTN[num][4]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][4]] & 0x80)
ret1 ^= JOY_TRG5;
if (Config.JOY_BTN[num][5]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][5]] & 0x80)
ret1 ^= JOY_TRG6;
if (Config.JOY_BTN[num][6]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][6]] & 0x80)
ret1 ^= JOY_TRG7;
if (Config.JOY_BTN[num][7]<joybtnnum[num])
if (state.rgbButtons[Config.JOY_BTN[num][7]] & 0x80)
ret1 ^= JOY_TRG8;
}
else if (hres == DIERR_INPUTLOST)
IDirectInputDevice2_Acquire(joy[num]);
}
JoyState0[num] = ret0;
JoyState1[num] = ret1;
}
#endif
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef winx68k_joy_h
#define winx68k_joy_h
#include "common.h"
#define JOY_UP 0x01
#define JOY_DOWN 0x02
#define JOY_LEFT 0x04
#define JOY_RIGHT 0x08
#define JOY_TRG2 0x20
#define JOY_TRG1 0x40
#define JOY_TRG5 0x01
#define JOY_TRG4 0x02
#define JOY_TRG3 0x04
#define JOY_TRG7 0x08
#define JOY_TRG8 0x20
#define JOY_TRG6 0x40
void Joystick_Init(void);
void Joystick_Cleanup(void);
void Joystick_Activate(UINT wParam);
BYTE FASTCALL Joystick_Read(BYTE num);
void FASTCALL Joystick_Write(BYTE num, BYTE data);
void FASTCALL Joystick_Update(void);
extern BYTE JoyKeyState;
#endif
+101
View File
@@ -0,0 +1,101 @@
/* $Id: juliet.c,v 1.2 2003/12/05 18:07:16 nonaka Exp $ */
#include "common.h"
#include "juliet.h"
#if 0
/*
* Juliet ダミー
*/
BOOL
juliet_load(void)
{
return FAILURE;
}
void
juliet_unload(void)
{
}
BOOL
juliet_prepare(void)
{
return FAILURE;
}
// ---- YM2151部
// リセットと同時に、OPMチップの有無も確認
void
juliet_YM2151Reset(void)
{
}
int
juliet_YM2151IsEnable(void)
{
return FALSE;
}
int
juliet_YM2151IsBusy(void)
{
return FALSE;
}
void
juliet_YM2151W(BYTE reg, BYTE data)
{
}
// ---- YMF288部
void
juliet_YMF288Reset(void)
{
}
int
juliet_YM288IsEnable(void)
{
return TRUE;
}
int
juliet_YM288IsBusy(void)
{
return 0;
}
void
juliet_YMF288A(BYTE addr, BYTE data)
{
}
void
juliet_YMF288B(BYTE addr, BYTE data)
{
}
void
juliet_YMF288W(BYTE addr, BYTE data)
{
}
BYTE
juliet_YMF288R(BYTE addr)
{
return 0xff;
}
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifdef __cplusplus
extern "C" {
#endif
#if 1
#define juliet_load()
#define juliet_unload()
#define juliet_prepare()
#define juliet_YM2151Reset()
#define juliet_YM2151IsEnable() FALSE
#define juliet_YM2151W(r,d)
#else
BOOL juliet_load(void);
void juliet_unload(void);
BOOL juliet_prepare(void);
void juliet_YM2151Reset(void);
int juliet_YM2151IsEnable(void);
int juliet_YM2151IsBusy(void);
void juliet_YM2151W(BYTE reg, BYTE data);
void juliet_YMF288Reset(void);
int juliet_YMF288Enable(void);
int juliet_YMF288IsBusy(void);
void juliet_YMF288A(BYTE addr, BYTE data);
void juliet_YMF288B(BYTE addr, BYTE data);
void juliet_YMF288W(BYTE addr, BYTE data);
BYTE juliet_YMF288R(BYTE addr);
#endif
#ifdef __cplusplus
}
#endif
+479
View File
@@ -0,0 +1,479 @@
/* $Id: keyboard.c,v 1.5 2008/11/09 14:46:46 nonaka Exp $ */
/*
* Copyright (c) 2003,2008 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "common.h"
#include "joystick.h"
#include "prop.h"
#include "keyboard.h"
#include "mfp.h"
BYTE KeyBufWP;
BYTE KeyBufRP;
BYTE KeyBuf[KeyBufSize];
BYTE KeyEnable = 1;
BYTE KeyIntFlag = 0;
extern BYTE traceflag;
void
Keyboard_Init(void)
{
KeyBufWP = 0;
KeyBufRP = 0;
ZeroMemory(KeyBuf, KeyBufSize);
KeyEnable = 1;
KeyIntFlag = 0;
}
// ----------------------------------
// てーぶる類
// ----------------------------------
#include <gdk/gdkkeysyms.h>
#define NC 0
BYTE KeyTable[512] = {
// , , , , , , , ; 0x00
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x08
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x10
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x18
NC, NC, NC, NC, NC, NC, NC, NC,
// SPC, ! , " , # , $ , % , & , ' ; 0x20
0x35,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
// ( , ) , * , + , , , - , . , / ; 0x28
0x09,0x0a,0x28,0x27,0x31,0x0c,0x32,0x33,
// 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ; 0x30
0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
// 8 , 9 , ; , : , < , = , > , ? ; 0x38
0x09,0x0a,0x28,0x27,0x31,0x0c,0x32,0x33,
// @ , A , B , C , D , E , F , G ; 0x40
0x1b,0x1e,0x2e,0x2c,0x20,0x13,0x21,0x22,
// H , I , J , K , L , M , N , O ; 0x48
0x23,0x18,0x24,0x25,0x26,0x30,0x2f,0x10,
// P , Q , R , S , T , U , V , W ; 0x50
0x1a,0x11,0x14,0x1f,0x15,0x17,0x2d,0x12,
// X , Y , Z , [ , \ , ] , ^ , _ ; 0x58
0x2b,0x16,0x2a,0x1c,0x0e,0x29,0x0d,0x34,
// ` , a , b , c , d , e , f , g ; 0x60
0x1b,0x1e,0x2e,0x2c,0x20,0x13,0x21,0x22,
// h , i , j , k , l , m , n , o ; 0x68
0x23,0x18,0x24,0x25,0x26,0x30,0x2f,0x19,
// p , q , r , s , t , u , v , w ; 0x70
0x1a,0x11,0x14,0x1f,0x15,0x17,0x2d,0x12,
// x , y , z , { , | , } , ~ , ; 0x78
0x2b,0x16,0x2a,0x1c,0x0e,0x29,0x0d, NC,
// , , , , , , , ; 0x80
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x88
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x90
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x98
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xa0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xa8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xb0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xb8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xc0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xc8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xe0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xe8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xf0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xf8
NC, NC, NC, NC, NC, NC, NC, NC,
// ;0x100
// , , , , , , , ; 0x00
NC, NC, NC, NC, NC, NC, NC, NC,
// BS, TAB, LF, CLR, , RET, , ; 0x08
0x0f,0x10,0x1d, NC, NC,0x1d, NC, NC,
// , , ,PAUS,SCRL,SYSQ, , ; 0x10
NC, NC, NC,0x61, NC, NC, NC, NC,
// , , , ESC, , , , ; 0x18
NC, NC, NC,0x01, NC, NC, NC, NC,
// ,KANJ,MUHE,HENM,HENK,RONM,HIRA,KATA ; 0x20
NC, NC,0x56, NC, NC, NC, NC, NC,
// HIKA,ZENK,HANK,ZNHN, ,KANA, , ; 0x28
NC, NC, NC, NC, NC, NC, NC, NC,
// ALNU, , , , , , , ; 0x30
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , ,ZKOU,MKOU, ; 0x38
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x40
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x48
NC, NC, NC, NC, NC, NC, NC, NC,
// HOME, ←, ↑, →, ↓,RLDN,RLUP, END ; 0x50
0x36,0x3b,0x3c,0x3d,0x3e,0x39,0x38,0x3a,
// , , , , , , , ; 0x58
NC, NC, NC, NC, NC, NC, NC, NC,
// ,PRNT, INS, , , , , ; 0x60
NC, NC,0x5e, NC, NC, NC, NC, NC,
// , , ,BREA, , , , ; 0x68
NC, NC, NC,0x61, NC, NC, NC, NC,
// , , , , , , , ; 0x70
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x78
NC, NC, NC, NC, NC, NC, NC, NC,
// <SPC, , , , , , , ; 0x80
NC, NC, NC, NC, NC, NC, NC, NC,
// ,<TAB, , , ,<ENT, , ; 0x88
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , ,<HOM,<←>,<↑> ; 0x90
NC, NC, NC, NC, NC,0x36,0x3b,0x3c,
// <→>,<↓>,<RDN,<RUP,<END, ,<INS,<DEL ; 0x98
0x3d,0x3e,0x39,0x38,0x3a, NC,0x5e,0x37,
// , , , , , , , ; 0xa0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , <*>, <+>, <,>, <->, <.>, </> ; 0xa8
NC, NC,0x41,0x46, NC,0x42,0x51,0x40,
// <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7> ; 0xb0
0x4f,0x4b,0x4c,0x4d,0x47,0x48,0x49,0x43,
// <8>, <9>, , , , , f.1, f.2 ; 0xb8
0x44,0x45, NC, NC, NC, NC,0x63,0x64,
// f.3, f.4, f.5, f.6, f.7, f.8, f.9,f.10 ; 0xc0
0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
// f.11,f.12,f.13,f.14,f.15, , , ; 0xc8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd8
NC, NC, NC, NC, NC, NC, NC, NC,
// ,SFTL,SFTR,CTLL,CTLR,CAPS, ,METL ; 0xe0
NC,0x70,0x70,0x71,0x71,0x5d, NC,0x55,
// METR,ALTL,ALTR, , , , , ; 0xe8
0x55,0x55,0x55, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xf0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , DEL ; 0xf8
NC, NC, NC, NC, NC, NC, NC,0x37
};
BYTE KeyTableMaster[512] = {
// , , , , , , , ; 0x00
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x08
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x10
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x18
NC, NC, NC, NC, NC, NC, NC, NC,
// SPC, ! , " , # , $ , % , & , ' ; 0x20
0x35,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
// ( , ) , * , + , , , - , . , / ; 0x28
0x09,0x0a,0x28,0x27,0x31,0x0c,0x32,0x33,
// 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ; 0x30
0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
// 8 , 9 , ; , : , < , = , > , ? ; 0x38
0x09,0x0a,0x28,0x27,0x31,0x0c,0x32,0x33,
// @ , A , B , C , D , E , F , G ; 0x40
0x1b,0x1e,0x2e,0x2c,0x20,0x13,0x21,0x22,
// H , I , J , K , L , M , N , O ; 0x48
0x23,0x18,0x24,0x25,0x26,0x30,0x2f,0x10,
// P , Q , R , S , T , U , V , W ; 0x50
0x1a,0x11,0x14,0x1f,0x15,0x17,0x2d,0x12,
// X , Y , Z , [ , \ , ] , ^ , _ ; 0x58
0x2b,0x16,0x2a,0x1c,0x0e,0x29,0x0d,0x34,
// ` , a , b , c , d , e , f , g ; 0x60
0x1b,0x1e,0x2e,0x2c,0x20,0x13,0x21,0x22,
// h , i , j , k , l , m , n , o ; 0x68
0x23,0x18,0x24,0x25,0x26,0x30,0x2f,0x19,
// p , q , r , s , t , u , v , w ; 0x70
0x1a,0x11,0x14,0x1f,0x15,0x17,0x2d,0x12,
// x , y , z , { , | , } , ~ , ; 0x78
0x2b,0x16,0x2a,0x1c,0x0e,0x29,0x0d, NC,
// , , , , , , , ; 0x80
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x88
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x90
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x98
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xa0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xa8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xb0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xb8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xc0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xc8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xe0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xe8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xf0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xf8
NC, NC, NC, NC, NC, NC, NC, NC,
// ;0x100
// , , , , , , , ; 0x00
NC, NC, NC, NC, NC, NC, NC, NC,
// BS, TAB, LF, CLR, , RET, , ; 0x08
0x0f,0x10,0x1d, NC, NC,0x1d, NC, NC,
// , , ,PAUS,SCRL,SYSQ, , ; 0x10
NC, NC, NC,0x61, NC, NC, NC, NC,
// , , , ESC, , , , ; 0x18
NC, NC, NC,0x01, NC, NC, NC, NC,
// ,KANJ,MUHE,HENM,HENK,RONM,HIRA,KATA ; 0x20
NC, NC,0x56, NC, NC, NC, NC, NC,
// HIKA,ZENK,HANK,ZNHN, ,KANA, , ; 0x28
NC, NC, NC, NC, NC, NC, NC, NC,
// ALNU, , , , , , , ; 0x30
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , ,ZKOU,MKOU, ; 0x38
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x40
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x48
NC, NC, NC, NC, NC, NC, NC, NC,
// HOME, ←, ↑, →, ↓,RLDN,RLUP, END ; 0x50
0x36, NC, NC, NC, NC,0x39,0x38,0x3a,
// , , , , , , , ; 0x58
NC, NC, NC, NC, NC, NC, NC, NC,
// ,PRNT, INS, , , , , ; 0x60
NC, NC,0x5e, NC, NC, NC, NC, NC,
// , , ,BREA, , , , ; 0x68
NC, NC, NC,0x61, NC, NC, NC, NC,
// , , , , , , , ; 0x70
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0x78
NC, NC, NC, NC, NC, NC, NC, NC,
// <SPC, , , , , , , ; 0x80
NC, NC, NC, NC, NC, NC, NC, NC,
// ,<TAB, , , ,<ENT, , ; 0x88
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , ,<HOM,<←>,<↑> ; 0x90
NC, NC, NC, NC, NC,0x36, NC, NC,
// <→>,<↓>,<RDN,<RUP,<END, ,<INS,<DEL ; 0x98
NC, NC,0x39,0x38,0x3a, NC,0x5e,0x37,
// , , , , , , , ; 0xa0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , <*>, <+>, <,>, <->, <.>, </> ; 0xa8
NC, NC,0x41,0x46, NC,0x42, NC,0x40,
// <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7> ; 0xb0
0x4f,0x4b,0x4c,0x4d,0x47,0x48,0x49,0x43,
// <8>, <9>, , , , , f.1, f.2 ; 0xb8
0x44,0x45, NC, NC, NC, NC,0x63,0x64,
// f.3, f.4, f.5, f.6, f.7, f.8, f.9,f.10 ; 0xc0
0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
// f.11,f.12,f.13,f.14,f.15, , , ; 0xc8
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xd8
NC, NC, NC, NC, NC, NC, NC, NC,
// ,SFTL,SFTR,CTLL,CTLR,CAPS, ,METL ; 0xe0
NC,0x70,0x70,0x71,0x71,0x5d, NC,0x55,
// METR,ALTL,ALTR, , , , , ; 0xe8
0x55,0x55,0x55, NC, NC, NC, NC, NC,
// , , , , , , , ; 0xf0
NC, NC, NC, NC, NC, NC, NC, NC,
// , , , , , , , DEL ; 0xf8
NC, NC, NC, NC, NC, NC, NC,0x37
};
// ----------------------------------
// WM_KEYDOWN~
// ----------------------------------
void
Keyboard_KeyDown(DWORD wp)
{
BYTE code;
BYTE newwp;
if (wp & ~0xff) {
if (wp == GDK_VoidSymbol)
code = NC;
else if ((wp & 0xff00) == 0xff00)
code = KeyTable[(wp & 0xff) | 0x100];
else
code = NC;
} else
code = KeyTable[wp & 0xff];
if (code != NC) {
newwp = ((KeyBufWP + 1) & (KeyBufSize - 1));
if (newwp != KeyBufRP) {
KeyBuf[KeyBufWP] = code;
KeyBufWP = newwp;
}
}
switch (wp) {
case GDK_Up:
if (!(JoyKeyState&JOY_DOWN))
JoyKeyState |= JOY_UP;
break;
case GDK_Down:
if (!(JoyKeyState&JOY_UP))
JoyKeyState |= JOY_DOWN;
break;
case GDK_Left:
if (!(JoyKeyState&JOY_RIGHT))
JoyKeyState |= JOY_LEFT;
break;
case GDK_Right:
if (!(JoyKeyState&JOY_LEFT))
JoyKeyState |= JOY_RIGHT;
break;
case GDK_Z:
case GDK_z:
if (Config.JoyKeyReverse)
JoyKeyState |= JOY_TRG2;
else
JoyKeyState |= JOY_TRG1;
break;
case GDK_X:
case GDK_x:
if (Config.JoyKeyReverse)
JoyKeyState |= JOY_TRG1;
else
JoyKeyState |= JOY_TRG2;
break;
}
}
// ----------------------------------
// WM_KEYUP
// ----------------------------------
void
Keyboard_KeyUp(DWORD wp)
{
BYTE code;
BYTE newwp;
if (wp & ~0xff) {
if (wp == GDK_VoidSymbol)
code = NC;
else if ((wp & 0xff00) == 0xff00)
code = KeyTable[(wp & 0xff) | 0x100];
else
code = NC;
} else
code = KeyTable[wp & 0xff];
if (code != NC) {
newwp = ((KeyBufWP + 1) & (KeyBufSize - 1));
if (newwp != KeyBufRP) {
KeyBuf[KeyBufWP] = code | 0x80;
KeyBufWP = newwp;
}
}
switch(wp) {
case GDK_Up:
JoyKeyState &= ~JOY_UP;
break;
case GDK_Down:
JoyKeyState &= ~JOY_DOWN;
break;
case GDK_Left:
JoyKeyState &= ~JOY_LEFT;
break;
case GDK_Right:
JoyKeyState &= ~JOY_RIGHT;
break;
case GDK_Z:
case GDK_z:
if (Config.JoyKeyReverse)
JoyKeyState &= ~JOY_TRG2;
else
JoyKeyState &= ~JOY_TRG1;
break;
case GDK_X:
case GDK_x:
if (Config.JoyKeyReverse)
JoyKeyState &= ~JOY_TRG1;
else
JoyKeyState &= ~JOY_TRG2;
break;
}
}
// ----------------------------------
// Key Check
// 1フレーム中に4回(2400bps/10bit/60fpsとすれば、だが)呼ばれて、MFPにデータを送る
// ----------------------------------
void
Keyboard_Int(void)
{
if (KeyBufRP != KeyBufWP) {
if (!KeyIntFlag) {
LastKey = KeyBuf[KeyBufRP];
KeyBufRP = ((KeyBufRP+1)&(KeyBufSize-1));
KeyIntFlag = 1;
MFP_Int(3);
}
} else if (!KeyIntFlag) {
LastKey = 0;
}
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _winx68k_keyboard
#define _winx68k_keyboard
#include "common.h"
#define KeyBufSize 128
extern BYTE KeyBuf[KeyBufSize];
extern BYTE KeyBufWP;
extern BYTE KeyBufRP;
extern BYTE KeyTable[512];
extern BYTE KeyTableMaster[512];
extern BYTE KeyEnable;
extern BYTE KeyIntFlag;
void Keyboard_KeyDown(DWORD vkcode);
void Keyboard_KeyUp(DWORD vkcode);
void Keyboard_Int(void);
#endif //_winx68k_keyboard
+68
View File
@@ -0,0 +1,68 @@
// ---------------------------------------------------------------------------------------
// KEYCONF.C - KeyConfig ÆþÎÏÂÔ¤Á¥À¥¤¥¢¥í¥°
// ---------------------------------------------------------------------------------------
#include "common.h"
#include "resource.h"
#include "keyconf.h"
#include "winx68k.h"
HWND hWndKeyConf = NULL;
WORD KeyConf_CodeW = 0;
DWORD KeyConf_CodeL = 0;
char KeyConfMessage[255];
int KeyConfFlag = 0;
LRESULT CALLBACK KeyConfProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_INITDIALOG:
// if (!KeyConfFlag) SetFocus(hWndKeyConf);
KeyConfFlag = 1;
KeyConf_CodeW = 0;
KeyConf_CodeL = 0;
// SetDlgItemText(hdlg, IDC_KEYCONF_DLG, KeyConfMessage);
//ShowWindow(hdlg, SW_HIDE);
return 0;
case WM_COMMAND:
if (IDCANCEL == LOWORD(wp))
{
EndDialog(hdlg, TRUE);
break;
}
return TRUE;
case WM_SYSCOMMAND:
return TRUE;
case WM_ACTIVATE:
SetFocus(hWndKeyConf);
break;
// case WM_CLOSE:
// EndDialog(hdlg, FALSE);
// return TRUE;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
if (wp==VK_F12)
{
EndDialog(hdlg, TRUE);
return TRUE;
}
// Error("Key Pressed.");
KeyConf_CodeW = wp;
KeyConf_CodeL = lp;
EndDialog(hdlg, TRUE);
return TRUE;
default:
// SetFocus(hWndKeyConf);
return FALSE;
}
return FALSE;
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef _x68_keyconf
#define _x68_keyconf
extern HWND hWndKeyConf;
extern WORD KeyConf_CodeW;
extern DWORD KeyConf_CodeL;
extern char KeyConfMessage[255];
LRESULT CALLBACK KeyConfProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
#endif // _x68_keyconf
+1102
View File
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
// X68KのCGROMを作る
// buf: 作る領域 (0xc0000バイト分のバッファ)
// x68030: X68030フォントを作るか? (現在無効)
// primaryface: 書体1 (主に16ドット用)
// secondaryface: 書体2 (主に24ドット用)
//
// 戻り値: FALSE: 失敗, TRUE: 成功
int make_cgromdat(BYTE *buf, int x68030, LPSTR primaryface, LPSTR secondaryface);
+243
View File
@@ -0,0 +1,243 @@
/* $Id: mouse.c,v 1.5 2008/11/08 02:24:18 nonaka Exp $ */
/*
* Copyright (c) 2003,2008 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "common.h"
#include "winx68k.h"
#include "prop.h"
#include "scc.h"
#include "crtc.h"
#include "mouse.h"
int MousePosX = 0;
int MousePosY = 0;
BYTE MouseStat = 0;
BYTE MouseSW = 0;
POINT CursorPos;
int mousex = 0, mousey = 0;
static GdkPixmap *cursor_pixmap;
static GdkCursor *cursor;
static void getmaincenter(GtkWidget *w, POINT *p);
void gdk_window_set_pointer(GdkWindow *window, gint x, gint y);
void Mouse_Init(void)
{
static gchar hide_cursor[16*16/8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static int inited = 0;
if (!inited) {
GtkWidget *w = window;
inited = 1;
cursor_pixmap = gdk_pixmap_create_from_data(w->window,
hide_cursor, 16, 16, 1, &w->style->black, &w->style->black);
cursor = gdk_cursor_new_from_pixmap(cursor_pixmap,
cursor_pixmap, &w->style->black, &w->style->black, 0, 0);
}
MousePosX = (TextDotX / 2);
MousePosY = (TextDotY / 2);
MouseStat = 0;
}
// ----------------------------------
// Mouse Event Occured
// ----------------------------------
void Mouse_Event(DWORD wparam, DWORD lparam)
{
if (MouseSW) {
switch (wparam) {
case 0: // マウス移動
MousePosX = (lparam >> 16) & 0xffff;
MousePosY = (lparam & 0xffff);
break;
case 1: // 左ボタン
if (lparam == TRUE)
MouseStat |= 1;
else
MouseStat &= 0xfe;
break;
case 2: // 右ボタン
if (lparam == TRUE)
MouseStat |= 2;
else
MouseStat &= 0xfd;
break;
default:
break;
}
}
}
// ----------------------------------
// Mouse Data send to SCC
// ----------------------------------
void Mouse_SetData(void)
{
POINT pt;
int x, y;
if (MouseSW) {
getmaincenter(window, &pt);
mousex += (MousePosX - pt.x) * Config.MouseSpeed;
mousey += (MousePosY - pt.y) * Config.MouseSpeed;
x = mousex / 10;
y = mousey / 10;
mousex -= x * 10;
mousey -= y * 10;
MouseSt = MouseStat;
if (x > 127) {
MouseSt |= 0x10;
MouseX = 127;
} else if (x < -128) {
MouseSt |= 0x20;
MouseX = -128;
} else {
MouseX = (signed char)x;
}
if (y > 127) {
MouseSt |= 0x40;
MouseY = 127;
} else if (y < -128) {
MouseSt |= 0x80;
MouseY = -128;
} else {
MouseY = (signed char)y;
}
gdk_window_set_pointer(window->window, pt.x, pt.y);
} else {
MouseSt = 0;
MouseX = 0;
MouseY = 0;
}
}
// ----------------------------------
// Start Capture
// ----------------------------------
void Mouse_StartCapture(int flag)
{
GtkWidget *w = window;
POINT pt;
if (flag && !MouseSW) {
int cx, cy;
gdk_window_get_pointer(w->window, &cx, &cy, NULL);
gdk_pointer_grab(w->window, TRUE, 0, w->window, cursor, 0);
getmaincenter(w, &pt);
gdk_window_set_pointer(w->window, pt.x, pt.y);
CursorPos.x = (WORD)cx;
CursorPos.y = (WORD)cy;
MouseSW = 1;
}
if (!flag && MouseSW) {
gdk_window_set_pointer(w->window, CursorPos.x, CursorPos.y);
gdk_pointer_ungrab(0);
MouseSW = 0;
}
}
void Mouse_ChangePos(void)
{
if (MouseSW) {
POINT pt;
getmaincenter(window, &pt);
gdk_window_set_pointer(window->window, pt.x, pt.y);
}
}
static void
getmaincenter(GtkWidget *w, POINT *p)
{
p->x = w->allocation.x + w->allocation.width / 2;
p->y = w->allocation.y + w->allocation.height / 2;
}
#if GTK_MAJOR_VERSION == 1
#include <gdk/gdkprivate.h>
void
gdk_window_set_pointer(GdkWindow *window, gint x, gint y)
{
GdkWindowPrivate *private;
if (!window)
window = (GdkWindow *)&gdk_root_parent;
private = (GdkWindowPrivate *)window;
if (private->destroyed)
return;
XWarpPointer(private->xdisplay, None, private->xwindow,
0, 0, 0, 0, x, y);
}
#else /* GTK_MAJOR_VERSION != 1 */
#include <gdk/gdkx.h>
void
gdk_window_set_pointer(GdkWindow *window, gint x, gint y)
{
GdkScreen *screen;
if (window == NULL) {
screen = gdk_screen_get_default();
window = gdk_screen_get_root_window(screen);
}
if (GDK_WINDOW_DESTROYED(window))
return;
XWarpPointer(GDK_WINDOW_XDISPLAY(window), None, GDK_WINDOW_XID(window),
0, 0, 0, 0, x, y);
}
#endif /* GTK_MAJOR_VERSION == 1 */
+17
View File
@@ -0,0 +1,17 @@
#ifndef _winx68k_mouse
#define _winx68k_mouse
#include "common.h"
extern int MousePosX;
extern int MousePosY;
extern BYTE MouseStat;
extern BYTE MouseSW;
void Mouse_Init(void);
void Mouse_Event(DWORD wparam, DWORD lparam);
void Mouse_SetData(void);
void Mouse_StartCapture(int flag);
void Mouse_ChangePos(void);
#endif //_winx68k_mouse
+178
View File
@@ -0,0 +1,178 @@
; Copyright (C) 1999 URURI
; nasm用マクロ
; 1999/08/21 作成
; 1999/10/10 幾つか追加
; 1999/10/27 aout対応
; 1999/11/07 pushf, popf のNASMのバグ対応
; 1999/12/02 for BCC ( Thanks to Miquel )
; for Windows Visual C++ -> define WIN32
; Borland or cygwin -> WIN32 and COFF
; for FreeBSD 2.x -> AOUT
; for TownsOS -> __tos__
; otherwise -> none
;名前の付け方
BITS 32
%ifdef WIN32
%define _NAMING
%define segment_code segment .text align=16 class=CODE use32
%define segment_data segment .data align=16 class=DATA use32
%ifdef __BORLANDC__
%define segment_bss segment .data align=16 class=DATA use32
%else
%define segment_bss segment .bss align=16 class=DATA use32
%endif
%elifdef AOUT
%define _NAMING
%define segment_code segment .text
%define segment_data segment .data
%define segment_bss segment .bss
%else
%define segment_code segment .text align=16 class=CODE use32
%define segment_data segment .data align=16 class=DATA use32
%define segment_bss segment .bss align=16 class=DATA use32
%endif
%ifdef __tos__
group CGROUP text
group DGROUP data
%endif
;単精度浮動小数点形式
%idefine float dword
%idefine fsize 4
%idefine fsizen(a) (fsize*(a))
;ワード形式
%idefine wsize 2
%idefine wsizen(a) (wsize*(a))
%idefine dwsize 4
%idefine dwsizen(a) (dwsize*(a))
;REG
%define r0 eax
%define r1 ebx
%define r2 ecx
%define r3 edx
%define r4 esi
%define r5 edi
%define r6 ebp
%define r7 esp
;MMX,3DNow!,SSE
%define pmov movq
%define pmovd movd
%define pupldq punpckldq
%define puphdq punpckhdq
%define puplwd punpcklwd
%define puphwd punpckhwd
%define xm0 xmm0
%define xm1 xmm1
%define xm2 xmm2
%define xm3 xmm3
%define xm4 xmm4
%define xm5 xmm5
%define xm6 xmm6
%define xm7 xmm7
;シャッフル用の4進マクロ
%define R4(a,b,c,d) (a*64+b*16+c*4+d)
;Cライクな簡易マクロ
%imacro globaldef 1
%ifdef _NAMING
%define %1 _%1
%endif
global %1
%endmacro
%imacro externdef 1
%ifdef _NAMING
%define %1 _%1
%endif
extern %1
%endmacro
%imacro proc 1
%push proc
%ifdef _NAMING
global _%1
%else
global %1
%endif
align 32
%1:
_%1:
%assign %$STACK 0
%assign %$STACKN 0
%assign %$ARG 4
%endmacro
%imacro endproc 0
%ifnctx proc
%error expected 'proc' before 'endproc'.
%else
%if %$STACK > 0
add esp, %$STACK
%endif
%if %$STACK <> (-%$STACKN)
%error STACKLEVEL mismatch check 'local', 'alloc', 'pushd', 'popd'
%endif
ret
%pop
%endif
%endmacro
%idefine sp(a) esp+%$STACK+a
%imacro arg 1
%00 equ %$ARG
%assign %$ARG %$ARG+%1
%endmacro
%imacro local 1
%assign %$STACKN %$STACKN-%1
%00 equ %$STACKN
%endmacro
%imacro alloc 0
sub esp, (-%$STACKN)-%$STACK
%assign %$STACK (-%$STACKN)
%endmacro
%imacro pushd 1-*
%rep %0
push %1
%assign %$STACK %$STACK+4
%rotate 1
%endrep
%endmacro
%imacro popd 1-*
%rep %0
%rotate -1
pop %1
%assign %$STACK %$STACK-4
%endrep
%endmacro
; bug of NASM-0.98
%define pushf db 0x66, 0x9C
%define popf db 0x66, 0x9D
+1294
View File
File diff suppressed because it is too large. Load diff
+57
View File
@@ -0,0 +1,57 @@
#ifndef _winx68k_config
#define _winx68k_config
#include "common.h"
typedef struct
{
DWORD SampleRate;
DWORD BufferSize;
int WinPosX;
int WinPosY;
int OPM_VOL;
int PCM_VOL;
int MCR_VOL;
int JOY_BTN[2][8];
int MouseSpeed;
int WindowFDDStat;
int FullScrFDDStat;
int DSAlert;
int MIDI_SW;
int MIDI_Type;
int MIDI_Reset;
int JoyKey;
int JoyKeyReverse;
int JoyKeyJoy2;
int SRAMWarning;
char HDImage[16][MAX_PATH];
int ToneMap;
char ToneMapFile[MAX_PATH];
int XVIMode;
int JoySwap;
int LongFileName;
int WinDrvFD;
int WinStrech;
int DSMixing;
int CDROM_ASPI;
int CDROM_ASPI_Drive;
int CDROM_IOCTRL_Drive;
int CDROM_SCSIID;
int CDROM_Enable;
int SSTP_Enable;
int SSTP_Port;
int Sound_LPF;
int SoundROMEO;
int MIDIDelay;
int MIDIAutoDelay;
} Win68Conf;
extern Win68Conf Config;
void LoadConfig(void);
void SaveConfig(void);
void PropPage_Init(void);
int set_modulepath(char *path, size_t len);
#endif //_winx68k_config
+344
View File
@@ -0,0 +1,344 @@
/* $Id: status.c,v 1.3 2008/11/08 01:42:42 nonaka Exp $ */
/*
* Copyright (c) 2003 NONAKA Kimihiro
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if 0
/* -------------------------------------------------------------------------- *
* FDD状態表示用ステータスバー *
* -------------------------------------------------------------------------- */
#include "common.h"
#include "windraw.h"
#include "winx68k.h"
#include "prop.h"
#include "status.h"
#include "fileio.h"
#include "fdd.h"
#if 0
#include "../icons/fd_inserted.xpm"
#include "../icons/fd_inuse.xpm"
#include "../icons/fd_normal.xpm"
#include "../icons/fd_protected.xpm"
#include "../icons/hd_inserted.xpm"
#include "../icons/hd_inuse.xpm"
#include "../icons/hd_normal.xpm"
#include "../icons/nulldev.xpm"
static char **pixmaps[] = {
fd_normal,
fd_inuse,
fd_inserted,
fd_protected,
hd_normal,
hd_inuse,
hd_inserted,
nulldev,
};
#endif
//static GtkWidget *statbar;
//static GtkWidget *devstat[2 /* FDD */ + 1 /* SASI */];
//static GtkWidget *devlabel[2 /* FDD */ + 1 /* SASI */];
//static GdkPixmap *devstat_pixmap[2 /* FDD */ + 1 /* SASI */];
//static GdkPixmap *dev_pixmap[NELEMENTS(pixmaps)];
typedef struct {
int insert;
int access;
int blink;
int timer;
char file[MAX_PATH];
} FDDLED;
static FDDLED FddLed[2];
//static int HddLed = 0, HddLedTmp = 0;
#if 0
/* ----- GTK signal handler */
static gint
expose(GtkWidget *w, GdkEventExpose *ev, gpointer d)
{
if (ev->type == GDK_EXPOSE) {
if (ev->count == 0) {
gdk_draw_pixmap(w->window,
w->style->fg_gc[GTK_WIDGET_STATE(w)],
devstat_pixmap[(int)d], 0, 0, 0, 0, 16, 16);
}
return TRUE;
}
return FALSE;
}
/* ----- */
#endif
void
StatBar_Redraw(void)
{
if (Config.FullScrFDDStat) {
StatBar_FDD(0, 0, FddLed[0].access);
StatBar_FDD(0, 1, FddLed[0].insert);
StatBar_FDD(1, 0, FddLed[1].access);
StatBar_FDD(1, 1, FddLed[1].insert);
StatBar_FDName(0, FddLed[0].file);
StatBar_FDName(1, FddLed[1].file);
}
}
void
StatBar_Show(int sw)
{
#if 1
(void)sw;
#else
if (sw) {
if (statbar == 0) {
GdkVisual *visual;
GdkColormap *colormap;
GdkBitmap *mask;
int pos = 0;
int i;
statbar = gtk_table_new(1, 18, FALSE);
gtk_box_pack_start(GTK_BOX(main_vbox), statbar,
FALSE, TRUE, 0);
colormap = gtk_widget_get_colormap(window);
for (i = 0; i < NELEMENTS(dev_pixmap); ++i) {
dev_pixmap[i] =
gdk_pixmap_colormap_create_from_xpm_d(NULL,
colormap, &mask, NULL, pixmaps[i]);
}
for (i = 0; i < NELEMENTS(devstat); ++i) {
GtkWidget *w;
int idx = 0;
if (i == NELEMENTS(devstat) - 1) {
w = gtk_vseparator_new();
gtk_table_attach(GTK_TABLE(statbar), w,
pos, pos + 1, 0, 1, 0, 0, 0, 0);
pos++;
gtk_widget_show(w);
idx += 4;
}
w = devstat[i] = gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA(w),
16, 16);
gtk_table_attach(GTK_TABLE(statbar), w,
pos, pos + 1, 0, 1, 0, 0, 0, 0);
pos++;
gtk_signal_connect(GTK_OBJECT(w),"expose_event",
GTK_SIGNAL_FUNC(expose), (gpointer)i);
gtk_widget_show(w);
devlabel[i] = gtk_label_new(
(i == NELEMENTS(devstat) - 1) ?
"HDD"
:
" "
" "
" "
" ");
gtk_table_attach_defaults(GTK_TABLE(statbar),
devlabel[i], pos, pos + 3, 0, 1);
pos += 3;
gtk_widget_show(devlabel[i]);
visual = gtk_widget_get_visual(w);
devstat_pixmap[i] = gdk_pixmap_new(w->window,
16, 16, visual->depth);
gdk_draw_pixmap(devstat_pixmap[i],
w->style->fg_gc[GTK_WIDGET_STATE(w)],
dev_pixmap[idx], 0, 0, 0, 0, 16, 16);
}
}
gtk_widget_show(statbar);
} else {
if (statbar)
gtk_widget_hide(statbar);
}
#endif
}
void
StatBar_UpdateTimer(void)
{
#if 0
FddLed[0].timer ^= 1;
FddLed[1].timer ^= 1;
if (FddLed[0].blink && (!FddLed[0].file[0]) && statbar) {
gdk_draw_pixmap(devstat_pixmap[0],
devstat[0]->style->fg_gc[GTK_WIDGET_STATE(devstat[0])],
dev_pixmap[FddLed[0].timer], 0, 0, 0, 0, 16, 16);
}
if (FddLed[1].blink && (!FddLed[1].file[0]) && statbar) {
gdk_draw_pixmap(devstat_pixmap[1],
devstat[1]->style->fg_gc[GTK_WIDGET_STATE(devstat[1])],
dev_pixmap[FddLed[1].timer], 0, 0, 0, 0, 16, 16);
}
if (HddLed != HddLedTmp) {
HddLed = HddLedTmp;
if (statbar) {
gdk_draw_pixmap(devstat_pixmap[2],
devstat[2]->style->fg_gc[
GTK_WIDGET_STATE(devstat[2])],
dev_pixmap[HddLed ? 5 : 4], 0, 0, 0, 0, 16, 16);
}
}
StatBar_Redraw();
#endif
}
void
StatBar_HDD(int hd)
{
#if 1
(void)hd;
#else
HddLedTmp = hd;
if ((HddLed != hd) && (hd)) {
gdk_draw_pixmap(devstat_pixmap[2],
devstat[2]->style->fg_gc[GTK_WIDGET_STATE(devstat[2])],
dev_pixmap[HddLed ? 5 : 4], 0, 0, 0, 0, 16, 16);
HddLed = hd;
}
StatBar_Redraw();
#endif
}
void
StatBar_SetFDD(int drv, char* file)
{
#if 1
(void)drv;
(void)file;
#else
char name[81];
char *f;
int i;
if ((drv < 0)||(drv > 1))
return;
f = (char *)getFileName(file);
strcpy(FddLed[drv].file, f);
g_snprintf(name, sizeof(name), "%s", f);
if (f[0]) {
FddLed[drv].access = 1;
FddLed[drv].insert = 1;
} else {
FddLed[drv].access = 0;
FddLed[drv].insert = 0;
}
if (statbar) {
int len = strlen(name);
int c = ((FddLed[drv].blink) && (!FddLed[drv].file[0])) ? FddLed[drv].timer : FddLed[drv].access;
gdk_draw_pixmap(devstat_pixmap[drv],
devstat[drv]->style->fg_gc[
GTK_WIDGET_STATE(devstat[drv])],
dev_pixmap[c], 0, 0, 0, 0, 16, 16);
memset(name + len, ' ', sizeof(name) - len);
name[80] = '\0';
gtk_label_set_text(devlabel[drv], name);
}
StatBar_Redraw();
#endif
}
void
StatBar_ParamFDD(int drv, int access, int insert, int blink)
{
#if 1
(void)drv;
(void)access;
(void)insert;
(void)blink;
#else
int update;
if ((drv < 0) || (drv > 1))
return;
update = 0;
if (FddLed[drv].access != access) {
FddLed[drv].access = access;
update = 1;
}
if (FddLed[drv].insert != insert) {
FddLed[drv].insert = insert;
update = 1;
}
if (FddLed[drv].blink != blink) {
FddLed[drv].blink = blink;
update = 1;
}
if (update) {
if (statbar) {
int c = ((FddLed[drv].blink) && (!FddLed[drv].file[0])) ? FddLed[drv].timer : FddLed[drv].access;
gdk_draw_pixmap(devstat_pixmap[drv],
devstat[drv]->style->fg_gc[
GTK_WIDGET_STATE(devstat[drv])],
dev_pixmap[c], 0, 0, 0, 0, 16, 16);
}
StatBar_Redraw();
}
#endif
}
void
StatBar_FDName(int drv, char* name)
{
/* Full screen 専用 */
(void)drv;
(void)name;
}
void
StatBar_FDD(int drv, int led, int col)
{
/* Full screen 専用 */
(void)drv;
(void)led;
(void)col;
}
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifndef winx68k_statusbar_h
#define winx68k_statusbar_h
#ifdef __cplusplus
extern "C" {
#endif
#if 1
#define StatBar_Show(s)
#define StatBar_UpdateTimer()
#define StatBar_SetFDD(d,f)
#define StatBar_ParamFDD(d,a,i,b)
#define StatBar_HDD(s)
#else
void StatBar_Redraw(void);
void StatBar_Show(int sw);
void StatBar_Draw(DRAWITEMSTRUCT* dis);
void StatBar_FDName(int drv, char* name);
void StatBar_FDD(int drv, int led, int col);
void StatBar_UpdateTimer(void);
void StatBar_SetFDD(int drv, char* file);
void StatBar_ParamFDD(int drv, int access, int insert, int blink);
void StatBar_HDD(int sw);
#endif
#ifdef __cplusplus
};
#endif
#endif //winx68k_statusbar_h
+36
View File
@@ -0,0 +1,36 @@
// -----------------------------------------------------------------------
// 55.6fps¥­¡¼¥×ÍѤ¿¤¤¤Þ¡¼
// -----------------------------------------------------------------------
#include "common.h"
#include "crtc.h"
#include "mfp.h"
DWORD timercnt = 0;
DWORD tick = 0;
void Timer_Init(void)
{
tick = timeGetTime();
}
void Timer_Reset(void)
{
tick = timeGetTime();
}
WORD Timer_GetCount(void)
{
DWORD ticknow = timeGetTime();
DWORD dif = ticknow-tick;
DWORD TIMEBASE = ((CRTC_Regs[0x29]&0x10)?VSYNC_HIGH:VSYNC_NORM);
timercnt += dif*10000;
tick = ticknow;
if ( timercnt>=TIMEBASE ) {
// timercnt = 0;
timercnt -= TIMEBASE;
if ( timercnt>=(TIMEBASE*2) ) timercnt = 0;
return 1;
} else
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef winx1_timer_h
#define winx1_timer_h
void Timer_Init(void);
void Timer_Reset(void);
WORD Timer_GetCount(void);
void Timer_SetCount(WORD);
#endif //winx1_timer_h
+15
View File
@@ -0,0 +1,15 @@
// ---------------------------------------------------------------------------
// WinX68k - SHARP X680x0 Emulator
// Copyright (C) Kenjo 2000
// ---------------------------------------------------------------------------
#ifndef _version_h
#define _version_h
#define APP_VER_MAJOR 0
#define APP_VER_MINOR 65
#define APP_VER_STRING "0.65"
#define SOURCE_VERSION "20081108"
#endif //_version_h
+2433
View File
File diff suppressed because it is too large. Load diff
+35
View File
@@ -0,0 +1,35 @@
/* $Id: windraw.h,v 1.1.1.1 2003/04/28 18:06:56 nonaka Exp $ */
#ifndef _winx68k_windraw_h
#define _winx68k_windraw_h
extern BYTE Draw_DrawFlag;
extern int winx, winy;
extern int winh, winw;
extern WORD *ScrBuf;
extern int FullScreenFlag;
extern BYTE Draw_ClrMenu;
extern WORD FrameCount;
extern WORD WinDraw_Pal16B, WinDraw_Pal16R, WinDraw_Pal16G;
extern BYTE Draw_BitMask[800];
extern BYTE Draw_TextBitMask[800];
extern int WindowX;
extern int WindowY;
void WinDraw_InitWindowSize(WORD width, WORD height);
void WinDraw_ChangeMode(int flag);
int WinDraw_Init(void);
void WinDraw_Cleanup(void);
void WinDraw_Redraw(void);
void FASTCALL WinDraw_Draw(void);
void WinDraw_ShowMenu(int flag);
void WinDraw_DrawLine(void);
void WinDraw_HideSplash(void);
void WinDraw_ChangeSize(void);
void WinDraw_StartupScreen(void);
void WinDraw_CleanupScreen(void);
#endif //winx68k_windraw_h
+1017
View File
File diff suppressed because it is too large. Load diff
+21
View File
@@ -0,0 +1,21 @@
/* $Id: winui.h,v 1.1.1.1 2003/04/28 18:06:56 nonaka Exp $ */
#ifndef _winx68k_winui_h
#define _winx68k_winui_h
extern BYTE Debug_Text, Debug_Grp, Debug_Sp;
extern DWORD LastClock[4];
void WinUI_Init(void);
#ifndef _winx68k_gtkui_h
#define _winx68k_gtkui_h
#include <gdk/gdk.h>
#include <gtk/gtk.h>
GtkWidget *create_menu(GtkWidget *w);
#endif //winx68k_gtkui_h
#endif //winx68k_winui_h
+747
View File
@@ -0,0 +1,747 @@
/* $Id: winx68k.cpp,v 1.2 2003/12/05 18:07:17 nonaka Exp $ */
#ifdef __cplusplus
extern "C" {
#endif
#include "common.h"
#include "fileio.h"
#include "timer.h"
#include "keyboard.h"
#include "prop.h"
#include "status.h"
#include "joystick.h"
#include "mkcgrom.h"
#include "winx68k.h"
#include "windraw.h"
#include "winui.h"
#include "m68000.h"
#include "memory.h"
#include "mfp.h"
#include "opm.h"
#include "bg.h"
#include "adpcm.h"
#include "mercury.h"
#include "crtc.h"
#include "mfp.h"
#include "fdc.h"
#include "fdd.h"
#include "dmac.h"
#include "irqh.h"
#include "ioc.h"
#include "rtc.h"
#include "sasi.h"
#include "scsi.h"
#include "bg.h"
#include "palette.h"
#include "crtc.h"
#include "pia.h"
#include "scc.h"
#include "midi.h"
#include "sram.h"
#include "gvram.h"
#include "tvram.h"
#include "mouse.h"
#include "dswin.h"
#include "fmg_wrap.h"
#ifdef WIN68DEBUG
#include "d68k.h"
#endif
#include "../icons/keropi_mono.xbm"
#define APPNAME "Keropi"
extern WORD BG_CHREND;
extern WORD BG_BGTOP;
extern WORD BG_BGEND;
extern BYTE BG_CHRSIZE;
const BYTE PrgName[] = "Keropi";
const BYTE PrgTitle[] = APPNAME;
char winx68k_dir[MAX_PATH];
char winx68k_ini[MAX_PATH];
WORD VLINE_TOTAL = 567;
DWORD VLINE = 0;
DWORD vline = 0;
extern int SplashFlag;
BYTE DispFrame = 0;
extern BYTE FrameRate;
DWORD SoundSampleRate;
int CurFrameRate = 1;
int NoWaitMode = 0;
unsigned int hTimerID = 0;
DWORD TimerICount = 0;
extern DWORD timertick;
BYTE traceflag = 0;
BYTE ForceDebugMode = 0;
DWORD skippedframes = 0;
static int ClkUsed = 0;
static int FrameSkipCount = 0;
static int FrameSkipQueue = 0;
GtkWidget *window;
GtkWidget *main_vbox;
GtkWidget *menubar;
GtkWidget *drawarea;
extern GdkImage *surface;
extern GdkPixmap *pixmap;
extern GdkPixmap *splash_pixmap;
static void set_window_size(GtkWidget *);
static void set_icon_bitmap(GtkWidget *);
typedef void sigfunc(int);
static sigfunc *setup_signal(int, sigfunc *);
static void sighandler(int);
#ifdef __cplusplus
};
#endif
void
WinX68k_SCSICheck(void)
{
static const BYTE SCSIIMG[] = {
0x00, 0xfc, 0x00, 0x14, // $fc0000 SCSI起動用のエントリアドレス
0x00, 0xfc, 0x00, 0x16, // $fc0004 IOCSベクタ設定のエントリアドレス(必ず"Human"の8バイト前)
0x00, 0x00, 0x00, 0x00, // $fc0008 ?
0x48, 0x75, 0x6d, 0x61, // $fc000c ↓
0x6e, 0x36, 0x38, 0x6b, // $fc0010 ID "Human68k" (必ず起動エントリポイントの直前)
0x4e, 0x75, // $fc0014 "rts" (起動エントリポイント)
0x23, 0xfc, 0x00, 0xfc, 0x00, 0x2a, // $fc0016 ↓ (IOCSベクタ設定エントリポイント)
0x00, 0x00, 0x07, 0xd4, // $fc001c "move.l #$fc002a, $7d4.l"
0x74, 0xff, // $fc0020 "moveq #-1, d2"
0x4e, 0x75, // $fc0022 "rts"
// 0x53, 0x43, 0x53, 0x49, 0x49, 0x4e, // $fc0024 ID "SCSIIN"
// 内蔵SCSIをONにすると、SASIは自動的にOFFになっちゃうらしい…
// よって、IDはマッチしないようにしておく…
0x44, 0x55, 0x4d, 0x4d, 0x59, 0x20, // $fc0024 ID "DUMMY "
0x70, 0xff, // $fc002a "moveq #-1, d0" (SCSI IOCSコールエントリポイント)
0x4e, 0x75, // $fc002c "rts"
};
DWORD *p;
int scsi;
int i;
scsi = 0;
for (i = 0x30600; i < 0x30c00; i += 2) {
p = (DWORD *)(&IPL[i]);
if (*p == 0x0000fc00)
scsi = 1;
}
// SCSIモデルのとき
if (scsi) {
ZeroMemory(IPL, 0x2000); // 本体は8kb
memset(&IPL[0x2000], 0xff, 0x1e000); // 残りは0xff
memcpy(IPL, SCSIIMG, sizeof(SCSIIMG)); // インチキSCSI BIOS
// Memory_SetSCSIMode();
} else {
// SASIモデルはIPLがそのまま見える
memcpy(IPL, &IPL[0x20000], 0x20000);
}
}
int
WinX68k_LoadROMs(void)
{
static const char *BIOSFILE[] = {
"iplrom.dat", "iplrom30.dat", "iplromco.dat", "iplromxv.dat"
};
static const char FONTFILE[] = "cgrom.dat";
static const char FONTFILETMP[] = "cgrom.tmp";
FILEH fp;
int i;
BYTE tmp;
for (fp = 0, i = 0; fp == 0 && i < NELEMENTS(BIOSFILE); ++i) {
fp = File_OpenCurDir((char *)BIOSFILE[i]);
}
if (fp == 0) {
Error("BIOS ROM イメージが見つかりません.");
return FALSE;
}
File_Read(fp, &IPL[0x20000], 0x20000);
File_Close(fp);
WinX68k_SCSICheck(); // SCSI IPLなら、$fc0000~にSCSI BIOSを置く
for (i = 0; i < 0x40000; i += 2) {
tmp = IPL[i];
IPL[i] = IPL[i + 1];
IPL[i + 1] = tmp;
}
fp = File_OpenCurDir((char *)FONTFILE);
if (fp == 0) {
// cgrom.tmpがある?
fp = File_OpenCurDir((char *)FONTFILETMP);
if (fp == 0) {
#if 1
// フォント生成 XXX
printf("フォントROMイメージが見つかりません\n");
return FALSE;
#else
MessageBox(hWndMain,
"フォントROMイメージが見つかりません.\nWindowsフォントから新規に作成します.",
"けろぴーのメッセージ", MB_ICONWARNING | MB_OK);
SSTP_SendMes(SSTPMES_MAKEFONT);
make_cgromdat(FONT, FALSE, "MS ゴシック", "MS 明朝");
//WinX68k_MakeFont();
//DialogBox(hInst, MAKEINTRESOURCE(IDD_PROGBAR),
// hWndMain, (DLGPROC)MakeFontProc);
fp = File_CreateCurDir(FONTFILETMP);
if (fp)
{
File_Write(fp, FONT, 0xc0000);
File_Close(fp);
return TRUE;
}
return TRUE;
#endif
}
}
File_Read(fp, FONT, 0xc0000);
File_Close(fp);
return TRUE;
}
int
WinX68k_Reset(void)
{
OPM_Reset();
ZeroMemory(&regs, sizeof(m68k_regs));
regs.a[7] = regs.isp = (IPL[0x30001]<<24)|(IPL[0x30000]<<16)|(IPL[0x30003]<<8)|IPL[0x30002];
regs.pc = (IPL[0x30005]<<24)|(IPL[0x30004]<<16)|(IPL[0x30007]<<8)|IPL[0x30006];
regs.sr_high = 0x27;
M68KRESET();
Memory_Init();
CRTC_Init();
DMA_Init();
MFP_Init();
FDC_Init();
FDD_Reset();
SASI_Init();
SCSI_Init();
IOC_Init();
SCC_Init();
PIA_Init();
RTC_Init();
TVRAM_Init();
GVRAM_Init();
BG_Init();
Pal_Init();
IRQH_Init();
MIDI_Init();
//WinDrv_Init();
m68000_ICount = 0;
m68000_ICountBk = 0;
ICount = 0;
DSound_Stop();
SRAM_VirusCheck();
//CDROM_Init();
DSound_Play();
return TRUE;
}
int
WinX68k_Init(void)
{
IPL = (BYTE*)malloc(0x40000);
MEM = (BYTE*)malloc(0xc00000);
FONT = (BYTE*)malloc(0xc0000);
if (MEM)
ZeroMemory(MEM, 0xc00000);
if (MEM && FONT && IPL)
return TRUE;
else
return FALSE;
}
void
WinX68k_Cleanup(void)
{
if (IPL) {
free(IPL);
IPL = 0;
}
if (MEM) {
free(MEM);
MEM = 0;
}
if (FONT) {
free(FONT);
FONT = 0;
}
}
#define CLOCK_SLICE 200
// -----------------------------------------------------------------------------------
// コアのめいんるーぷ
// -----------------------------------------------------------------------------------
void WinX68k_Exec(void)
{
//char *test = NULL;
int clk_total, clkdiv, usedclk, hsync, clk_next, clk_count, clk_line=0;
int KeyIntCnt = 0, MouseIntCnt = 0;
DWORD t_start = timeGetTime(), t_end;
if ( FrameRate!=7 ) {
DispFrame = (DispFrame+1)%FrameRate;
} else { // Auto Frame Skip
if ( FrameSkipQueue ) {
if ( FrameSkipCount>15 ) {
FrameSkipCount = 0;
FrameSkipQueue++;
DispFrame = 0;
} else {
FrameSkipCount++;
FrameSkipQueue--;
DispFrame = 1;
}
} else {
FrameSkipCount = 0;
DispFrame = 0;
}
}
vline = 0;
clk_count = -ICount;
clk_total = (CRTC_Regs[0x29] & 0x10) ? VSYNC_HIGH : VSYNC_NORM;
if (Config.XVIMode == 1) {
clk_total = (clk_total*16)/10;
clkdiv = 16;
} else if (Config.XVIMode == 2) {
clk_total = (clk_total*24)/10;
clkdiv = 24;
} else {
clkdiv = 10;
}
ICount += clk_total;
clk_next = (clk_total/VLINE_TOTAL);
hsync = 1;
do {
int m, n = (ICount>CLOCK_SLICE)?CLOCK_SLICE:ICount;
m68000_ICount = m68000_ICountBk = 0; // 割り込み発生前に与えておかないとダメ(CARAT)
if ( hsync ) {
hsync = 0;
clk_line = 0;
MFP_Int(0);
if ( (vline>=CRTC_VSTART)&&(vline<CRTC_VEND) )
VLINE = ((vline-CRTC_VSTART)*CRTC_VStep)/2;
else
VLINE = (DWORD)-1;
if ( (!(MFP[MFP_AER]&0x40))&&(vline==CRTC_IntLine) )
MFP_Int(1);
if ( MFP[MFP_AER]&0x10 ) {
if ( vline==CRTC_VSTART )
MFP_Int(9);
} else {
if ( CRTC_VEND>=VLINE_TOTAL ) {
if ( (long)vline==(CRTC_VEND-VLINE_TOTAL) ) MFP_Int(9); // エキサイティングアワーとか(TOTAL<VEND)
} else {
if ( (long)vline==(VLINE_TOTAL-1) ) MFP_Int(9); // クレイジークライマーはコレでないとダメ?
}
}
}
#ifdef WIN68DEBUG
if (traceflag/*&&fdctrace*/)
{
FILE *fp;
static DWORD oldpc;
int i;
char buf[200];
fp=fopen("_trace68.txt", "a");
for (i=0; i<HSYNC_CLK; i++)
{
m68k_disassemble(buf, regs.pc);
// if (MEM[0xa84c0]) /**test=1; */tracing=1000;
// if (regs.pc==0x9d2a) tracing=5000;
// if ((regs.pc>=0x2000)&&((regs.pc<=0x8e0e0))) tracing=50000;
// if (regs.pc<0x10000) tracing=1;
// if ( (regs.pc&1) )
// fp=fopen("_trace68.txt", "a");
// if ( (regs.pc==0x7176) /*&& (Memory_ReadW(oldpc)==0xff1a)*/ ) tracing=100;
// if ( (/*((regs.pc>=0x27000) && (regs.pc<=0x29000))||*/((regs.pc>=0x27000) && (regs.pc<=0x29000))) && (oldpc!=regs.pc))
if (/*fdctrace&&*/(oldpc!=regs.pc))
{
// //tracing--;
fprintf(fp, "D0:%08X D1:%08X D2:%08X D3:%08X D4:%08X D5:%08X D6:%08X D7:%08X CR:%04X\n", regs.d[0], regs.d[1], regs.d[2], regs.d[3], regs.d[4], regs.d[5], regs.d[6], regs.d[7], regs.ccr);
fprintf(fp, "A0:%08X A1:%08X A2:%08X A3:%08X A4:%08X A5:%08X A6:%08X A7:%08X SR:%04X\n", regs.a[0], regs.a[1], regs.a[2], regs.a[3], regs.a[4], regs.a[5], regs.a[6], regs.a[7], regs.sr_high);
fprintf(fp, "<%04X> (%08X ->) %08X : %s\n", Memory_ReadW(regs.pc), oldpc, regs.pc, buf);
}
oldpc = regs.pc;
m68000_ICount = 1;
M68KRUN();
}
fclose(fp);
usedclk = clk_line = HSYNC_CLK;
clk_count = clk_next;
}
else
#endif
{
m68000_ICount = n;
M68KRUN();
m = (n-m68000_ICount-m68000_ICountBk); // 経過クロック数
ClkUsed += m*10;
usedclk = ClkUsed/clkdiv;
clk_line += usedclk;
ClkUsed -= usedclk*clkdiv;
ICount -= m;
clk_count += m;
m68000_ICount = m68000_ICountBk = 0;
}
MFP_Timer(usedclk);
RTC_Timer(usedclk);
DMA_Exec(0);
DMA_Exec(1);
DMA_Exec(2);
if ( clk_count>=clk_next ) {
//OPM_RomeoOut(Config.BufferSize*5);
MIDI_DelayOut((Config.MIDIAutoDelay)?(Config.BufferSize*5):Config.MIDIDelay);
MFP_TimerA();
if ( (MFP[MFP_AER]&0x40)&&(vline==CRTC_IntLine) )
MFP_Int(1);
if ( (!DispFrame)&&(vline>=CRTC_VSTART)&&(vline<CRTC_VEND) ) {
if ( CRTC_VStep==1 ) { // HighReso 256dot(2度読み)
if ( vline%2 )
WinDraw_DrawLine();
} else if ( CRTC_VStep==4 ) { // LowReso 512dot
WinDraw_DrawLine(); // 1走査線で2回描く(インターレース)
VLINE++;
WinDraw_DrawLine();
} else { // High 512dot / Low 256dot
WinDraw_DrawLine();
}
}
ADPCM_PreUpdate(clk_line);
OPM_Timer(clk_line);
MIDI_Timer(clk_line);
#ifndef NO_MERCURY
Mcry_PreUpdate(clk_line);
#endif
KeyIntCnt++;
if ( KeyIntCnt>(VLINE_TOTAL/4) ) {
KeyIntCnt = 0;
Keyboard_Int();
}
MouseIntCnt++;
if ( MouseIntCnt>(VLINE_TOTAL/8) ) {
MouseIntCnt = 0;
SCC_IntCheck();
}
DSound_Send0(clk_line); // Bufferがでかいとき用
vline++;
clk_next = (clk_total*(vline+1))/VLINE_TOTAL;
hsync = 1;
}
} while ( vline<VLINE_TOTAL );
if ( CRTC_Mode&2 ) { // FastClrビットの調整(PITAPAT)
if ( CRTC_FastClr ) { // FastClr=1 且つ CRTC_Mode&2 なら 終了
CRTC_FastClr--;
if ( !CRTC_FastClr )
CRTC_Mode &= 0xfd;
} else { // FastClr開始
if ( CRTC_Regs[0x29]&0x10 )
CRTC_FastClr = 1;
else
CRTC_FastClr = 2;
TVRAM_SetAllDirty();
GVRAM_FastClear();
}
}
Joystick_Update();
DSound_Send();
FDD_SetFDInt();
if ( !DispFrame )
WinDraw_Draw();
TimerICount += clk_total;
t_end = timeGetTime();
if ( (int)(t_end-t_start)>((CRTC_Regs[0x29]&0x10)?14:16) ) {
FrameSkipQueue += ((t_end-t_start)/((CRTC_Regs[0x29]&0x10)?14:16))+1;
if ( FrameSkipQueue>100 )
FrameSkipQueue = 100;
}
}
/*
* signal handler
*/
static sigfunc *
setup_signal(int signo, sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;
return oact.sa_handler;
}
static void
sighandler(int signo)
{
UNUSED(signo);
gtk_main_quit();
}
/*
* misc
*/
static void
set_window_size(GtkWidget *w)
{
/* リサイズ不可 */
gtk_window_set_policy(GTK_WINDOW(w), FALSE, FALSE, TRUE);
}
static void
set_icon_bitmap(GtkWidget *w)
{
GdkPixmap *icon_pixmap;
gdk_window_set_icon_name(w->window, APPNAME);
icon_pixmap = gdk_bitmap_create_from_data(
w->window, keropi_mono_bits, keropi_mono_width, keropi_mono_height);
gdk_window_set_icon(w->window, NULL, icon_pixmap, NULL);
}
//
// IDLE process
//
static gint
idle_process_splash(gpointer *p)
{
UNUSED(p);
// OPM_RomeoOut(Config.BufferSize * 5);
if (NoWaitMode || Timer_GetCount()) {
WinX68k_Exec();
if (SplashFlag) {
SplashFlag--;
if (SplashFlag == 0)
WinDraw_HideSplash();
}
}
return TRUE;
}
static int idle_id = -1;
BOOL
is_installed_idle_process(void)
{
return (idle_id == -1) ? FALSE : TRUE;
}
void
install_idle_process(void)
{
idle_id = gtk_idle_add((GtkFunction)idle_process_splash, NULL);
}
void
uninstall_idle_process(void)
{
gtk_idle_remove(idle_id);
idle_id = -1;
}
//
// main
//
int
main(int argc, char *argv[])
{
if (set_modulepath(winx68k_dir, sizeof(winx68k_dir)))
return 1;
dosio_init();
file_setcd(winx68k_dir);
LoadConfig();
gtk_set_locale();
gtk_rc_add_default_file(".xkeropirc");
gtk_init(&argc, &argv);
/* ウィンドウの作成 */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
main_vbox = gtk_vbox_new(FALSE, 2);
gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
gtk_container_add(GTK_CONTAINER(window), main_vbox);
gtk_widget_show(main_vbox);
/* メニューバー */
menubar = create_menu(window);
gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
gtk_widget_show(menubar);
/* 画面領域 */
drawarea = gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA(drawarea),
FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT);
gtk_box_pack_start(GTK_BOX(main_vbox), drawarea, FALSE, TRUE, 0);
gtk_widget_show(drawarea);
gtk_widget_realize(window);
gtk_widget_set_uposition(GTK_WIDGET(window), winx, winy);
/* タイトルやらアイコンやらのセットアップ */
gtk_window_set_title(GTK_WINDOW(window), APPNAME);
set_window_size(window);
set_icon_bitmap(window);
SplashFlag = 20;
SoundSampleRate = Config.SampleRate;
StatBar_Show(Config.WindowFDDStat);
WinDraw_ChangeSize();
WinDraw_ChangeMode(FALSE);
WinUI_Init();
WinDraw_StartupScreen();
if (!WinDraw_Init()) {
WinDraw_Cleanup();
Error("Error: Can't init screen.\n");
return 1;
}
/* window 表示 */
gtk_widget_show(window);
if (!WinX68k_Init()) {
WinX68k_Cleanup();
WinDraw_Cleanup();
return 1;
}
if (!WinX68k_LoadROMs()) {
WinX68k_Cleanup();
WinDraw_Cleanup();
return 1;
}
if ( SoundSampleRate ) {
ADPCM_Init(SoundSampleRate);
OPM_Init(4000000/*3579545*/, SoundSampleRate);
#ifndef NO_MERCURY
Mcry_Init(SoundSampleRate, winx68k_dir);
#endif
} else {
ADPCM_Init(100);
OPM_Init(4000000/*3579545*/, 100);
#ifndef NO_MERCURY
Mcry_Init(100, winx68k_dir);
#endif
}
Mouse_Init();
Joystick_Init();
SRAM_Init();
WinX68k_Reset();
Timer_Init();
MIDI_Init();
MIDI_SetMimpiMap(Config.ToneMapFile); // 音色設定ファイル使用反映
MIDI_EnableMimpiDef(Config.ToneMap);
if (!DSound_Init(Config.SampleRate, Config.BufferSize)) {
if (Config.DSAlert)
fprintf(stderr, "Can't init sound.\n");
}
ADPCM_SetVolume((BYTE)Config.PCM_VOL);
OPM_SetVolume((BYTE)Config.OPM_VOL);
#ifndef NO_MERCURY
Mcry_SetVolume((BYTE)Config.MCR_VOL);
#endif
DSound_Play();
//SetCmdLineFD(); // コマンドラインでFD挿入を指示している場合
switch (argc) {
case 3:
FDD_SetFD(1, argv[2], 0);
case 2:
FDD_SetFD(0, argv[1], 0);
break;
}
setup_signal(SIGINT, sighandler);
setup_signal(SIGTERM, sighandler);
/* メインループ */
install_idle_process();
gtk_main();
uninstall_idle_process();
Memory_WriteB(0xe8e00d, 0x31); // SRAM書き込み許可
Memory_WriteD(0xed0040, Memory_ReadD(0xed0040)+1); // 積算稼働時間(min.)
Memory_WriteD(0xed0044, Memory_ReadD(0xed0044)+1); // 積算起動回数
OPM_Cleanup();
#ifndef NO_MERCURY
Mcry_Cleanup();
#endif
SRAM_Cleanup();
FDD_Cleanup();
//CDROM_Cleanup();
MIDI_Cleanup();
Joystick_Cleanup();
DSound_Cleanup();
WinX68k_Cleanup();
WinDraw_Cleanup();
WinDraw_CleanupScreen();
SaveConfig();
return 0;
}
+50
View File
@@ -0,0 +1,50 @@
#ifndef winx68k_wincore_h
#define winx68k_wincore_h
#define SCREEN_WIDTH 768
#define SCREEN_HEIGHT 512
#define FULLSCREEN_WIDTH 800
#define FULLSCREEN_HEIGHT 600
#define FULLSCREEN_POSX ((FULLSCREEN_WIDTH - SCREEN_WIDTH) / 2)
#define FULLSCREEN_POSY ((FULLSCREEN_HEIGHT - SCREEN_HEIGHT) / 2)
extern BYTE* FONT;
extern WORD VLINE_TOTAL;
extern DWORD VLINE;
extern DWORD vline;
extern char winx68k_dir[MAX_PATH];
extern char winx68k_ini[MAX_PATH];
extern int BIOS030Flag;
extern BYTE FrameChanged;
extern const BYTE PrgTitle[];
int WinX68k_Reset(void);
#ifndef winx68k_gtkwarpper_h
#define winx68k_gtkwarpper_h
#include <unistd.h>
#include <signal.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
extern GtkWidget *window;
extern GtkWidget *main_vbox;
extern GtkWidget *menubar;
extern GtkWidget *drawarea;
extern GdkPixmap *splash_pixmap;
BOOL is_installed_idle_process(void);
void install_idle_process(void);
void uninstall_idle_process(void);
#define NELEMENTS(array) ((int)(sizeof(array) / sizeof(array[0])))
#endif //winx68k_gtkwarpper_h
#endif //winx68k_wincore_h
+56435
View File
File diff suppressed because it is too large. Load diff
+331
View File
@@ -0,0 +1,331 @@
// ---------------------------------------------------------------------------------------
// ADPCM.C - ADPCM (OKI MSM6258V)
// な~んか、X68Sound.dllに比べてカシャカシャした音になるんだよなぁ……
// DSoundのクセってのもあるけど、それだけじゃなさそうな気もする
// ---------------------------------------------------------------------------------------
#include <math.h>
#include "common.h"
#include "prop.h"
#include "pia.h"
#include "adpcm.h"
#include "dmac.h"
#define ADPCM_BufSize 96000
#define ADPCMMAX 2047
#define ADPCMMIN -2048
#define FM_IPSCALE 256L
#define OVERSAMPLEMUL 2
#define INTERPOLATE(y, x) \
(((((((-y[0]+3*y[1]-3*y[2]+y[3]) * x + FM_IPSCALE/2) / FM_IPSCALE \
+ 3 * (y[0]-2*y[1]+y[2])) * x + FM_IPSCALE/2) / FM_IPSCALE \
- 2*y[0]-3*y[1]+6*y[2]-y[3]) * x + 3*FM_IPSCALE) / (6*FM_IPSCALE) + y[1])
static int ADPCM_VolumeShift = 65536;
static const int index_shift[16] = {
-1*16, -1*16, -1*16, -1*16, 2*16, 4*16, 6*16, 8*16,
-1*16, -1*16, -1*16, -1*16, 2*16, 4*16, 6*16, 8*16 };
static const int ADPCM_Clocks[8] = {
93750, 125000, 187500, 125000, 46875, 62500, 93750, 62500 };
static int dif_table[49*16];
static signed short ADPCM_BufR[ADPCM_BufSize];
static signed short ADPCM_BufL[ADPCM_BufSize];
static long ADPCM_WrPtr = 0;
static long ADPCM_RdPtr = 0;
static DWORD ADPCM_SampleRate = 44100*12;
DWORD ADPCM_ClockRate = 7800*12;
static DWORD ADPCM_Count = 0;
static int ADPCM_Step = 0;
static int ADPCM_Out = 0;
static BYTE ADPCM_Playing = 0;
BYTE ADPCM_Clock = 0;
static int ADPCM_PreCounter = 0;
static int ADPCM_DifBuf = 0;
static int ADPCM_Pan = 0x00;
static int OldR = 0, OldL = 0;
static int Outs[8];
static int OutsIp[4];
static int OutsIpR[4];
static int OutsIpL[4];
int ADPCM_IsReady(void)
{
return 1;
}
// -----------------------------------------------------------------------
// てーぶる初期化
// -----------------------------------------------------------------------
static void ADPCM_InitTable(void)
{
int step, n;
double val;
static int bit[16][4] =
{
{ 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1},
{ 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1},
{-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},
{-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}
};
for (step=0; step<=48; step++) {
val = floor(16.0 * pow ((double)1.1, (double)step));
for (n=0; n<16; n++) {
dif_table[step*16+n] = bit[n][0] *
(int)(val * bit[n][1] +
val/2 * bit[n][2] +
val/4 * bit[n][3] +
val/8);
}
}
}
#define LimitMix(val) { \
if ( val > 0x7fff ) val = 0x7fff; \
else if ( val < -0x8000 ) val = -0x8000; \
}
// -----------------------------------------------------------------------
// MPUクロック経過分だけバッファにデータを溜めておく
// -----------------------------------------------------------------------
void FASTCALL ADPCM_PreUpdate(DWORD clock)
{
/*if (!ADPCM_Playing) return;*/
ADPCM_PreCounter += ((ADPCM_ClockRate/24)*clock);
while ( ADPCM_PreCounter>=10000000L ) { // ↓ データの送りすぎ防止(A-JAX)。200サンプリングくらいまでは許そう…。
ADPCM_DifBuf -= ( (ADPCM_SampleRate*400)/ADPCM_ClockRate );
if ( ADPCM_DifBuf<=0 ) {
ADPCM_DifBuf = 0;
DMA_Exec(3);
}
ADPCM_PreCounter -= 10000000L;
}
}
// -----------------------------------------------------------------------
// DSoundが指定してくる分だけバッファにデータを書き出す
// -----------------------------------------------------------------------
void FASTCALL ADPCM_Update(signed short *buffer, DWORD length)
{
int outs;
signed int outl, outr;
if ( length<=0 ) return;
while ( length ) {
int tmp;
if ( (ADPCM_WrPtr==ADPCM_RdPtr)&&(!(DMA[3].CCR&0x40)) ) DMA_Exec(3);
if ( ADPCM_WrPtr!=ADPCM_RdPtr ) {
OldR = outr = ADPCM_BufL[ADPCM_RdPtr];
OldL = outl = ADPCM_BufR[ADPCM_RdPtr];
ADPCM_RdPtr++;
if ( ADPCM_RdPtr>=ADPCM_BufSize ) ADPCM_RdPtr = 0;
} else {
outr = OldR;
outl = OldL;
}
if ( Config.Sound_LPF ) {
outr = (int)(outr*40*ADPCM_VolumeShift);
outs = (outr + Outs[3]*2 + Outs[2] + Outs[1]*157 - Outs[0]*61) >> 8;
Outs[2] = Outs[3];
Outs[3] = outr;
Outs[0] = Outs[1];
Outs[1] = outs;
} else {
outs = (int)(outr*ADPCM_VolumeShift);
}
OutsIpR[0] = OutsIpR[1];
OutsIpR[1] = OutsIpR[2];
OutsIpR[2] = OutsIpR[3];
OutsIpR[3] = outs;
if ( Config.Sound_LPF ) {
outl = (int)(outl*40*ADPCM_VolumeShift);
outs = (outl + Outs[7]*2 + Outs[6] + Outs[5]*157 - Outs[4]*61) >> 8;
Outs[6] = Outs[7];
Outs[7] = outl;
Outs[4] = Outs[5];
Outs[5] = outs;
} else {
outs = (int)(outl*ADPCM_VolumeShift);
}
OutsIpL[0] = OutsIpL[1];
OutsIpL[1] = OutsIpL[2];
OutsIpL[2] = OutsIpL[3];
OutsIpL[3] = outs;
#if 1
tmp = INTERPOLATE(OutsIpR, 0);
if ( tmp>32767 ) tmp = 32767; else if ( tmp<(-32768) ) tmp = -32768;
*(buffer++) = (short)tmp;
tmp = INTERPOLATE(OutsIpL, 0);
if ( tmp>32767 ) tmp = 32767; else if ( tmp<(-32768) ) tmp = -32768;
*(buffer++) = (short)tmp;
#else
*(buffer++) = (short)OutsIpR[3];
*(buffer++) = (short)OutsIpL[3];
#endif
length--;
}
ADPCM_DifBuf = ADPCM_WrPtr-ADPCM_RdPtr;
if ( ADPCM_DifBuf<0 ) ADPCM_DifBuf += ADPCM_BufSize;
}
// -----------------------------------------------------------------------
// 1nibble(4bit)をデコード
// -----------------------------------------------------------------------
INLINE void ADPCM_WriteOne(int val)
{
ADPCM_Out += dif_table[ADPCM_Step+val];
if ( ADPCM_Out>ADPCMMAX ) ADPCM_Out = ADPCMMAX; else if ( ADPCM_Out<ADPCMMIN ) ADPCM_Out = ADPCMMIN;
ADPCM_Step += index_shift[val];
if ( ADPCM_Step>(48*16) ) ADPCM_Step = (48*16); else if ( ADPCM_Step<0 ) ADPCM_Step = 0;
if ( OutsIp[0]==-1 ) {
OutsIp[0] =
OutsIp[1] =
OutsIp[2] =
OutsIp[3] = ADPCM_Out;
} else {
OutsIp[0] = OutsIp[1];
OutsIp[1] = OutsIp[2];
OutsIp[2] = OutsIp[3];
OutsIp[3] = ADPCM_Out;
}
while ( ADPCM_SampleRate>ADPCM_Count ) {
if ( ADPCM_Playing ) {
int ratio = (((ADPCM_Count/100)*FM_IPSCALE)/(ADPCM_SampleRate/100));
int tmp = INTERPOLATE(OutsIp, ratio);
if ( tmp>ADPCMMAX ) tmp = ADPCMMAX; else if ( tmp<ADPCMMIN ) tmp = ADPCMMIN;
if ( !(ADPCM_Pan&1) )
ADPCM_BufR[ADPCM_WrPtr] = (short)tmp;
else
ADPCM_BufR[ADPCM_WrPtr] = 0;
if ( !(ADPCM_Pan&2) )
ADPCM_BufL[ADPCM_WrPtr++] = (short)tmp;
else
ADPCM_BufL[ADPCM_WrPtr++] = 0;
if ( ADPCM_WrPtr>=ADPCM_BufSize ) ADPCM_WrPtr = 0;
}
ADPCM_Count += ADPCM_ClockRate;
}
ADPCM_Count -= ADPCM_SampleRate;
}
// -----------------------------------------------------------------------
// I/O Write
// -----------------------------------------------------------------------
void FASTCALL ADPCM_Write(DWORD adr, BYTE data)
{
if ( adr==0xe92001 ) {
if ( data&1 ) {
ADPCM_Playing = 0;
} else if ( data&2 ) {
if ( !ADPCM_Playing ) {
ADPCM_Step = 0;
ADPCM_Out = 0;
OldL = OldR = -2;
ADPCM_Playing = 1;
}
OutsIp[0] = OutsIp[1] = OutsIp[2] = OutsIp[3] = -1;
}
} else if ( adr==0xe92003 ) {
if ( ADPCM_Playing ) {
ADPCM_WriteOne((int)(data&15));
ADPCM_WriteOne((int)((data>>4)&15));
}
}
}
// -----------------------------------------------------------------------
// I/O Read(ステータスチェック)
// -----------------------------------------------------------------------
BYTE FASTCALL ADPCM_Read(DWORD adr)
{
if ( adr==0xe92001 )
return ((ADPCM_Playing)?0xc0:0x40);
else
return 0x00;
}
// -----------------------------------------------------------------------
// ぼりゅーむ
// -----------------------------------------------------------------------
void ADPCM_SetVolume(BYTE vol)
{
if ( vol>16 ) vol=16;
// if ( vol<0 ) vol=0;
if ( vol )
ADPCM_VolumeShift = (int)((double)16/pow(1.189207115, (16-vol)));
else
ADPCM_VolumeShift = 0; // Mute
}
// -----------------------------------------------------------------------
// Panning
// -----------------------------------------------------------------------
void ADPCM_SetPan(int n)
{
if ( (ADPCM_Pan&0x0c)!=(n&0x0c) ) {
ADPCM_Count = 0;
ADPCM_Clock = (ADPCM_Clock&4)|((n>>2)&3);
ADPCM_ClockRate = ADPCM_Clocks[ADPCM_Clock];
}
ADPCM_Pan = n;
}
// -----------------------------------------------------------------------
// Clock
// -----------------------------------------------------------------------
void ADPCM_SetClock(int n)
{
if ( (ADPCM_Clock&4)!=n ) {
ADPCM_Count = 0;
ADPCM_Clock = n|((ADPCM_Pan>>2)&3);
ADPCM_ClockRate = ADPCM_Clocks[ADPCM_Clock];
}
}
// -----------------------------------------------------------------------
// 初期化
// -----------------------------------------------------------------------
void ADPCM_Init(DWORD samplerate)
{
ADPCM_WrPtr = 0;
ADPCM_RdPtr = 0;
ADPCM_Out = 0;
ADPCM_Step = 0;
ADPCM_Playing = 0;
ADPCM_SampleRate = (samplerate*12);
ADPCM_PreCounter = 0;
memset(Outs, 0, sizeof(Outs));
OutsIp[0] = OutsIp[1] = OutsIp[2] = OutsIp[3] = -1;
OutsIpR[0] = OutsIpR[1] = OutsIpR[2] = OutsIpR[3] = 0;
OutsIpL[0] = OutsIpL[1] = OutsIpL[2] = OutsIpL[3] = 0;
OldL = OldR = 0;
ADPCM_SetPan(0x0b);
ADPCM_InitTable();
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _winx68k_adpcm_h
#define _winx68k_adpcm_h
extern BYTE ADPCM_Clock;
extern DWORD ADPCM_ClockRate;
void FASTCALL ADPCM_PreUpdate(DWORD clock);
void FASTCALL ADPCM_Update(signed short *buffer, DWORD length);
void FASTCALL ADPCM_Write(DWORD adr, BYTE data);
BYTE FASTCALL ADPCM_Read(DWORD adr);
void ADPCM_SetVolume(BYTE vol);
void ADPCM_SetPan(int n);
void ADPCM_SetClock(int n);
void ADPCM_Init(DWORD samplerate);
int ADPCM_IsReady(void);
#endif
+608
View File
@@ -0,0 +1,608 @@
// ---------------------------------------------------------------------------------------
// BG.C - BGとスプライト
// ToDo:透明色の処理チェック(特に対Text間)
// ---------------------------------------------------------------------------------------
#include "common.h"
#include "windraw.h"
#include "winx68k.h"
#include "palette.h"
#include "tvram.h"
#include "crtc.h"
#include "bg.h"
#include "m68000.h"
#include "memory.h"
BYTE BG[0x8000];
BYTE Sprite_Regs[0x800];
BYTE BG_Regs[0x12];
WORD BG_CHREND = 0;
WORD BG_BG0TOP = 0;
WORD BG_BG0END = 0;
WORD BG_BG1TOP = 0;
WORD BG_BG1END = 0;
BYTE BG_CHRSIZE = 16;
DWORD BG_AdrMask = 511;
DWORD BG0ScrollX = 0, BG0ScrollY = 0;
DWORD BG1ScrollX = 0, BG1ScrollY = 0;
long BG_HAdjust = 0;
long BG_VLINE = 0;
BYTE BG_Dirty0[64*64];
BYTE BG_Dirty1[64*64];
BYTE BGCHR8[8*8*256];
BYTE BGCHR16[16*16*256];
WORD BG_LineBuf[1600];
WORD BG_PriBuf[1600];
DWORD VLINEBG = 0;
// -----------------------------------------------------------------------
// 初期化
// -----------------------------------------------------------------------
void BG_Init(void)
{
DWORD i;
ZeroMemory(Sprite_Regs, 0x800);
ZeroMemory(BG, 0x8000);
ZeroMemory(BGCHR8, 8*8*256);
ZeroMemory(BGCHR16, 16*16*256);
ZeroMemory(BG_LineBuf, 1600*2);
for (i=0; i<0x12; i++)
BG_Write(0xeb0800+i, 0);
BG_CHREND = 0x8000;
}
// -----------------------------------------------------------------------
// I/O Read
// -----------------------------------------------------------------------
BYTE FASTCALL BG_Read(DWORD adr)
{
if ((adr>=0xeb0000)&&(adr<0xeb0400))
{
adr -= 0xeb0000;
adr ^= 1;
return Sprite_Regs[adr];
}
else if ((adr>=0xeb0800)&&(adr<0xeb0812))
return BG_Regs[adr-0xeb0800];
else if ((adr>=0xeb8000)&&(adr<0xec0000))
return BG[adr-0xeb8000];
else
return 0xff;
}
// -----------------------------------------------------------------------
// I/O Write
// -----------------------------------------------------------------------
void FASTCALL BG_Write(DWORD adr, BYTE data)
{
DWORD bg16chr;
int s1, s2, v = 0;
s1 = (((BG_Regs[0x11] &4)?2:1)-((BG_Regs[0x11] &16)?1:0));
s2 = (((CRTC_Regs[0x29]&4)?2:1)-((CRTC_Regs[0x29]&16)?1:0));
if ( !(BG_Regs[0x11]&16) ) v = ((BG_Regs[0x0f]>>s1)-(CRTC_Regs[0x0d]>>s2));
if ((adr>=0xeb0000)&&(adr<0xeb0400))
{
adr &= 0x3ff;
adr ^= 1;
if (Sprite_Regs[adr] != data)
{
#ifdef USE_ASM
_asm
{
mov ebx, adr
and ebx, 3f8h
mov bx, word ptr Sprite_Regs[ebx+2]
sub bx, 16
add ebx, BG_VLINE
sub ebx, v
and ebx, 3ffh
mov al, 16
spsetdirtylp1:
mov byte ptr TextDirtyLine[ebx], 1
inc bx
and bx, 3ffh
dec al
jnz spsetdirtylp1
}
Sprite_Regs[adr] = data;
_asm
{
mov ebx, adr
and ebx, 3f8h
mov bx, word ptr Sprite_Regs[ebx+2]
sub bx, 16
add ebx, BG_VLINE
sub ebx, v
and ebx, 3ffh
mov al, 16
spsetdirtylp2:
mov byte ptr TextDirtyLine[ebx], 1
inc bx
and bx, 3ffh
dec al
jnz spsetdirtylp2
}
#elif defined(USE_GAS) && defined(__i386__)
asm (
"mov %0, %%ebx;"
"and $0x3f8, %%ebx;"
"mov Sprite_Regs + 2(%%ebx), %%bx;"
"sub $16, %%bx;"
"add (%1), %%ebx;"
"sub %2, %%ebx;"
"and $0x3ff, %%ebx;"
"mov $16, %%al;"
"0:"
"movb $1, TextDirtyLine(%%ebx);"
"inc %%bx;"
"and $0x3ff, %%bx;"
"dec %%al;"
"jnz 0b;"
: /* output: nothing */
: "m" (adr), "g" (BG_VLINE), "m" (v)
: "ax", "bx", "memory");
Sprite_Regs[adr] = data;
asm (
"mov %0, %%ebx;"
"and $0x3f8, %%ebx;"
"mov Sprite_Regs + 2(%%ebx), %%bx;"
"sub $16, %%bx;"
"add (%1), %%ebx;"
"sub %2, %%ebx;"
"and $0x3ff, %%ebx;"
"mov $16, %%al;"
"0:"
"movb $1, TextDirtyLine(%%ebx);"
"inc %%bx;"
"and $0x3ff, %%bx;"
"dec %%al;"
"jnz 0b;"
: /* output: nothing */
: "m" (adr), "g" (BG_VLINE), "m" (v)
: "ax", "bx", "memory");
#else /* !USE_ASM && !(USE_GAS && __i386__) */
WORD t, *pw = (WORD *)Sprite_Regs;
int i;
t = (pw[((adr-v) & 0x3f8) + 1] - 16 + BG_VLINE) & 0x3ff;
for (i = 0; i < 16; i++) {
TextDirtyLine[t] = 1;
t = (t + 1) & 0x3ff;
}
Sprite_Regs[adr] = data;
t = (pw[((adr-v) & 0x3f8) + 1] - 16 + BG_VLINE) & 0x3ff;
for (i = 0; i < 16; i++) {
TextDirtyLine[t] = 1;
t = (t + 1) & 0x3ff;
}
#endif /* USE_ASM */
}
}
else if ((adr>=0xeb0800)&&(adr<0xeb0812))
{
adr -= 0xeb0800;
if (BG_Regs[adr]==data) return; // データに変化が無ければ帰る
BG_Regs[adr] = data;
switch(adr)
{
case 0x00:
case 0x01:
BG0ScrollX = (((DWORD)BG_Regs[0x00]<<8)+BG_Regs[0x01])&BG_AdrMask;
TVRAM_SetAllDirty();
break;
case 0x02:
case 0x03:
BG0ScrollY = (((DWORD)BG_Regs[0x02]<<8)+BG_Regs[0x03])&BG_AdrMask;
TVRAM_SetAllDirty();
break;
case 0x04:
case 0x05:
BG1ScrollX = (((DWORD)BG_Regs[0x04]<<8)+BG_Regs[0x05])&BG_AdrMask;
TVRAM_SetAllDirty();
break;
case 0x06:
case 0x07:
BG1ScrollY = (((DWORD)BG_Regs[0x06]<<8)+BG_Regs[0x07])&BG_AdrMask;
TVRAM_SetAllDirty();
break;
case 0x08: // BG On/Off Changed
TVRAM_SetAllDirty();
break;
case 0x0d:
BG_HAdjust = ((long)BG_Regs[0x0d]-(CRTC_HSTART+4))*8; // 水平方向は解像度による1/2はいらない?(Tetris)
TVRAM_SetAllDirty();
break;
case 0x0f:
BG_VLINE = ((long)BG_Regs[0x0f]-CRTC_VSTART)/((BG_Regs[0x11]&4)?1:2); // BGとその他がずれてる時の差分
TVRAM_SetAllDirty();
break;
case 0x11: // BG ScreenRes Changed
if (data&3)
{
if ((BG_BG0TOP==0x4000)||(BG_BG1TOP==0x4000))
BG_CHREND = 0x4000;
else if ((BG_BG0TOP==0x6000)||(BG_BG1TOP==0x6000))
BG_CHREND = 0x6000;
else
BG_CHREND = 0x8000;
}
else
BG_CHREND = 0x2000;
BG_CHRSIZE = ((data&3)?16:8);
BG_AdrMask = ((data&3)?1023:511);
BG_HAdjust = ((long)BG_Regs[0x0d]-(CRTC_HSTART+4))*8; // 水平方向は解像度による1/2はいらない?(Tetris)
BG_VLINE = ((long)BG_Regs[0x0f]-CRTC_VSTART)/((BG_Regs[0x11]&4)?1:2); // BGとその他がずれてる時の差分
break;
case 0x09: // BG Plane Cfg Changed
TVRAM_SetAllDirty();
if (data&0x08)
{
if (data&0x30)
{
BG_BG1TOP = 0x6000;
BG_BG1END = 0x8000;
}
else
{
BG_BG1TOP = 0x4000;
BG_BG1END = 0x6000;
}
}
else
BG_BG1TOP = BG_BG1END = 0;
if (data&0x01)
{
if (data&0x06)
{
BG_BG0TOP = 0x6000;
BG_BG0END = 0x8000;
}
else
{
BG_BG0TOP = 0x4000;
BG_BG0END = 0x6000;
}
}
else
BG_BG0TOP = BG_BG0END = 0;
if (BG_Regs[0x11]&3)
{
if ((BG_BG0TOP==0x4000)||(BG_BG1TOP==0x4000))
BG_CHREND = 0x4000;
else if ((BG_BG0TOP==0x6000)||(BG_BG1TOP==0x6000))
BG_CHREND = 0x6000;
else
BG_CHREND = 0x8000;
}
break;
case 0x0b:
break;
}
Draw_DrawFlag = 1;
}
else if ((adr>=0xeb8000)&&(adr<0xec0000))
{
adr -= 0xeb8000;
if (BG[adr]==data) return; // データに変化が無ければ帰る
BG[adr] = data;
if (adr<0x2000)
{
BGCHR8[adr*2] = data>>4;
BGCHR8[adr*2+1] = data&15;
}
bg16chr = ((adr&3)*2)+((adr&0x3c)*4)+((adr&0x40)>>3)+((adr&0x7f80)*2);
BGCHR16[bg16chr] = data>>4;
BGCHR16[bg16chr+1] = data&15;
if (adr<BG_CHREND) // パターンエリア
{
TVRAM_SetAllDirty();
}
if ((adr>=BG_BG1TOP)&&(adr<BG_BG1END)) // BG1 MAPエリア
{
TVRAM_SetAllDirty();
}
if ((adr>=BG_BG0TOP)&&(adr<BG_BG0END)) // BG0 MAPエリア
{
TVRAM_SetAllDirty();
}
}
}
#ifndef USE_GAS
#define USE_GAS
#endif
// -----------------------------------------------------------------------
// 1ライン分の描画
// -----------------------------------------------------------------------
#ifdef USE_ASM
#include "bg.x86"
LABEL void FASTCALL BG_DrawLine(int opaq, int gd) {
__asm {
pushf
push ebx
push esi
push edi
push edx
push ebp
//xor eax, eax
mov ax, TextPal[0]
shl eax, 16
mov ax, TextPal[0]
mov ebx, 0xffffffff
mov edi, 16*2
or ecx, ecx // ecx = opaq
jz noclrloop
mov ecx, TextDotX
shr ecx, 1
BGLineClr_lp:
mov dword ptr BG_LineBuf[edi], eax
mov dword ptr BG_PriBuf[edi], ebx // SP間のプライオリティ情報初期化
add edi, 4
loop BGLineClr_lp
jmp bgclrloopend
noclrloop:
mov ecx, TextDotX
shr ecx, 1
BGLineClr_lp2:
mov dword ptr BG_PriBuf[edi], ebx // SP間のプライオリティ情報初期化
add edi, 4
loop BGLineClr_lp2
bgclrloopend:
or edx, edx // edx = gd
je BG_NOGRP
cmp BG_CHRSIZE, 8
jne BG16
Sprite_DrawLineMcr(81, 1)
; test BG_Regs[9], 8
; je BG8_1skiped
; BG_DrawLineMcr8(1, BG_BG1TOP, BG1ScrollX, BG1ScrollY)
; BG8_1skiped:
Sprite_DrawLineMcr(82, 2)
test BG_Regs[9], 1
je BG_0skiped
BG_DrawLineMcr8(0, BG_BG0TOP, BG0ScrollX, BG0ScrollY)
jmp BG_0skiped
BG16:
Sprite_DrawLineMcr(161, 1)
; test BG_Regs[9], 8
; je BG16_1skiped
; BG_DrawLineMcr16(1, BG_BG1TOP, BG1ScrollX, BG1ScrollY)
; BG16_1skiped:
Sprite_DrawLineMcr(162, 2)
test BG_Regs[9], 1
je BG_0skiped
BG_DrawLineMcr16(0, BG_BG0TOP, BG0ScrollX, BG0ScrollY)
jmp BG_0skiped
BG_NOGRP:
cmp BG_CHRSIZE, 8
jne BG16_ng
Sprite_DrawLineMcr(ng81, 1)
test BG_Regs[9], 8
je BG8_ng_1skiped
BG_DrawLineMcr8_ng(1, BG_BG1TOP, BG1ScrollX, BG1ScrollY)
BG8_ng_1skiped:
Sprite_DrawLineMcr(ng82, 2)
test BG_Regs[9], 1
je BG_0skiped
BG_DrawLineMcr8_ng(0, BG_BG0TOP, BG0ScrollX, BG0ScrollY)
jmp BG_0skiped
BG16_ng:
Sprite_DrawLineMcr(ng161, 1)
test BG_Regs[9], 8
je BG16_ng_1skiped
BG_DrawLineMcr16_ng(1, BG_BG1TOP, BG1ScrollX, BG1ScrollY)
BG16_ng_1skiped:
Sprite_DrawLineMcr(ng162, 2)
test BG_Regs[9], 1
je BG_0skiped
BG_DrawLineMcr16_ng(0, BG_BG0TOP, BG0ScrollX, BG0ScrollY)
BG_0skiped:
Sprite_DrawLineMcr(163, 3)
pop ebp
pop edx
pop edi
pop esi
pop ebx
popf
ret
}
}
#elif defined(USE_GAS) && defined(__i386__)
#if 0
LABEL void FASTCALL BG_DrawLine(int opaq, int gd) {
extern LABEL void FASTCALL __BG_DrawLine(int opaq, int gd);
__BG_DrawLine(opaq, gd);
}
#endif
#else /* !USE_ASM && !(USE_GAS && __i386__) */
struct SPRITECTRLTBL {
WORD sprite_posx;
WORD sprite_posy;
WORD sprite_ctrl;
BYTE sprite_ply;
BYTE dummy;
} __attribute__ ((packed));
typedef struct SPRITECTRLTBL SPRITECTRLTBL_T;
INLINE void
Sprite_DrawLineMcr(int pri)
{
SPRITECTRLTBL_T *sct = (SPRITECTRLTBL_T *)Sprite_Regs;
DWORD y;
DWORD t;
int n;
for (n = 127; n >= 0; --n) {
if ((sct[n].sprite_ply & 3) == pri) {
SPRITECTRLTBL_T *sctp = &sct[n];
t = (sctp->sprite_posx + BG_HAdjust) & 0x3ff;
if (t > TextDotX + 16)
continue;
y = sct->sprite_posy & 0x3ff;
y -= VLINEBG;
y += BG_VLINE;
y = -y;
y += 16;
// add y, 16; jnc .spline_lpcnt
if (y <= 15) {
BYTE *p;
DWORD pal;
int i;
if (sctp->sprite_ctrl < 0x4000) {
// spline_flipx
p = &BGCHR16[(sctp->sprite_ctrl * 256) + (y * 16)];
for (i = 0; i < 16; ++i, ++t) {
pal = *p++ & 0xf;
if (pal) {
pal |= (sctp->sprite_ctrl >> 4) & 0xf0;
if (BG_PriBuf[t] >= n) {
BG_LineBuf[t] = TextPal[pal];
Text_TrFlag[t] |= 2;
BG_PriBuf[t] = n;
}
}
}
} else {
// spline_fxflipx
p = &BGCHR16[(sctp->sprite_ctrl * 256) + (y * 16)];
for (i = 0; i < 16; ++i, ++t) {
pal = *p-- & 0xf;
if (pal) {
pal |= (sctp->sprite_ctrl >> 4) & 0xf0;
if (BG_PriBuf[t] >= n) {
BG_LineBuf[t] = TextPal[pal];
Text_TrFlag[t] |= 2;
BG_PriBuf[t] = n;
}
}
}
}
}
}
}
}
INLINE void
BG_DrawLineMcr8(int bg)
{
WORD *bgtop;
DWORD *bgscrx, *bgscry;
DWORD x, y;
DWORD t0, t1;
if (bg == 0) {
bgtop = &BG_BG0TOP;
bgscrx = &BG0ScrollX;
bgscry = &BG0ScrollY;
} else {
bgtop = &BG_BG1TOP;
bgscrx = &BG1ScrollX;
bgscry = &BG1ScrollY;
}
t0 = (*bgscry + VLINEBG) - BG_VLINE;
t1 = *bgscrx - BG_HAdjust;
y = *bgtop + (t0 & 0x1f8) << 4;
x = (y1 & 0x1f8) >> 2;
esi = BG[x + y];
}
INLINE void
BG_DrawLineMcr16(int bg)
{
}
INLINE void
BG_DrawLineMcr8_ng(int bg)
{
}
INLINE void
BG_DrawLineMcr16_ng(int bg)
{
}
LABEL void FASTCALL
BG_DrawLine(int opaq, int gd)
{
int i;
if (opaq) {
for (i = 16; i < TextDotX + 16; ++i) {
BG_LineBuf[i] = TextPal[0];
BG_PriBuf[i] = 0xffff;
}
} else {
for (i = 16; i < TextDotX + 16; ++i) {
BG_PriBuf[i] = 0xffff;
}
}
if (gd) {
Sprite_DrawLineMcr(1);
Sprite_DrawLineMcr(2);
if (BG_Regs[9] & 1) {
if (BG_CHRSIZE == 8) {
BG_DrawLineMcr8(0);
} else {
BG_DrawLineMcr16(0);
}
}
} else {
Sprite_DrawLineMcr(1);
if (BG_CHRSIZE == 8) {
if (BG_Regs[9] & 8) {
BG_DrawLineMcr8_ng(1);
}
Sprite_DrawLineMcr(2);
if (BG_Regs[9] & 1) {
BG_DrawLineMcr8_ng(0);
}
} else {
if (BG_Regs[9] & 8) {
BG_DrawLineMcr16_ng(1);
}
Sprite_DrawLineMcr(2);
if (BG_Regs[9] & 1) {
BG_DrawLineMcr16_ng(0);
}
}
}
Sprite_DrawLineMcr(3);
}
#endif /* USE_ASM */
+29
View File
@@ -0,0 +1,29 @@
#ifndef _winx68k_bg
#define _winx68k_bg
#include "common.h"
extern BYTE BG_DrawWork0[1024*1024];
extern BYTE BG_DrawWork1[1024*1024];
extern DWORD BG0ScrollX, BG0ScrollY;
extern DWORD BG1ScrollX, BG1ScrollY;
extern DWORD BG_AdrMask;
extern BYTE BG_CHRSIZE;
extern BYTE BG_Regs[0x12];
extern WORD BG_BG0TOP;
extern WORD BG_BG1TOP;
extern long BG_HAdjust;
extern long BG_VLINE;
extern DWORD VLINEBG;
extern BYTE Sprite_DrawWork[1024*1024];
extern WORD BG_LineBuf[1600];
void BG_Init(void);
BYTE FASTCALL BG_Read(DWORD adr);
void FASTCALL BG_Write(DWORD adr, BYTE data);
void FASTCALL BG_DrawLine(int opaq, int gd);
#endif
+346
View File
@@ -0,0 +1,346 @@
#define BGOUT_BUFFER (BG_LineBuf) // �o—̓oƒbƒtƒ@‚Û‚¢‚ñ‚½
#define BG_DrawLineMcr8(label, bgtop, scrx, scry) \
__asm { mov edx, scry } \
__asm { add edx, VLINEBG } \
__asm { sub edx, BG_VLINE } \
__asm { mov ebp, edx } \
__asm { and ebp, 7 } \
__asm { shl bp, 3 } \
__asm { and edx, 01f8h } \
__asm { shl edx, 4 } \
__asm { add dx, bgtop } \
__asm { mov eax, scrx } \
__asm { sub eax, BG_HAdjust } \
__asm { mov ecx, eax } \
__asm { and eax, 7 } \
__asm { xor al, 15 } \
__asm { mov edi, eax } \
__asm { and ecx, 01f8h } \
__asm { shr cx, 2 } \
__asm { mov ebx, TextDotX } \
__asm { shl ebx, 13 } \
bg8_##label##_linelp: \
__asm { movzx esi, word ptr BG[ecx+edx] } \
__asm { mov bx, si } \
__asm { and si, 0ff00h } \
__asm { shr si, 2 } \
__asm { cmp bl, 40h } \
__asm { jc bg8_##label##_flipx } \
__asm { js bg8_##label##_fxflipy } \
__asm { jge bg8_##label##_fxflipx } \
__asm { add esi, offset BGCHR8 + 00000038h } \
__asm { sub esi, ebp } \
__asm { jmp bg8_##label##_flip } \
bg8_##label##_fxflipy: \
__asm { add esi, offset BGCHR8 + 0000003fh } \
__asm { sub esi, ebp } \
__asm { std } \
__asm { jmp bg8_##label##_out } \
bg8_##label##_fxflipx: \
__asm { lea esi, BGCHR8[esi+ebp+7] } \
__asm { std } \
__asm { jmp bg8_##label##_out } \
bg8_##label##_flipx: \
__asm { lea esi, BGCHR8[esi+ebp] } \
bg8_##label##_flip: \
__asm { cld } \
bg8_##label##_out: \
__asm { mov bh, 8 } \
__asm { shl bl, 4 } \
bg8_##label##_outlp: \
__asm { lodsb } \
__asm { or al, bl } \
__asm { and ax, 00ffh } \
__asm { je bg8_##label##_outed } \
__asm { test ax, 000fh } \
__asm { mov ax, word ptr TextPal[eax*2] } \
__asm { jne bg8_##label##_outcont } \
__asm { test byte ptr (Text_TrFlag+1)[edi], 2 } \
__asm { jne bg8_##label##_outed } \
bg8_##label##_outcont: \
__asm { mov word ptr (BG_LineBuf+2)[edi*2], ax } \
__asm { or byte ptr (Text_TrFlag+1)[edi], 2 } \
bg8_##label##_outed: \
__asm { inc edi } \
__asm { dec bh } \
__asm { jne bg8_##label##_outlp } \
__asm { add cl, 2 } \
__asm { and cl, 7fh } \
__asm { sub ebx, 10000h } \
__asm { jns bg8_##label##_linelp }
#define BG_DrawLineMcr16(label, bgtop, scrx, scry) \
__asm { mov edx, scry } \
__asm { add edx, VLINEBG } \
__asm { sub edx, BG_VLINE } \
__asm { mov ebp, edx } \
__asm { and ebp, 15 } \
__asm { shl bp, 4 } \
__asm { and edx, 03f0h } \
__asm { shl edx, 3 } \
__asm { add dx, bgtop } \
__asm { mov eax, scrx } \
__asm { sub eax, BG_HAdjust } \
__asm { mov ecx, eax } \
__asm { and eax, 15 } \
__asm { xor al, 15 } \
__asm { mov edi, eax } \
__asm { and ecx, 03f0h } \
__asm { shr cx, 3 } \
__asm { mov ebx, TextDotX } \
__asm { shl ebx, 12 } \
bg16_##label##_linelp: \
__asm { movzx esi, word ptr BG[ecx+edx] } \
__asm { mov bx, si } \
__asm { and si, 0ff00h } \
__asm { cmp bl, 40h } \
__asm { jc bg16_##label##_flipx } \
__asm { js bg16_##label##_fxflipy } \
__asm { jge bg16_##label##_fxflipx } \
__asm { add esi, offset BGCHR16 + 000000f0h } \
__asm { sub esi, ebp } \
__asm { jmp bg16_##label##_flip } \
bg16_##label##_fxflipy: \
__asm { add esi, offset BGCHR16 + 000000ffh } \
__asm { sub esi, ebp } \
__asm { std } \
__asm { jmp bg16_##label##_out } \
bg16_##label##_fxflipx: \
__asm { lea esi, BGCHR16[esi+ebp+15] } \
__asm { std } \
__asm { jmp bg16_##label##_out } \
bg16_##label##_flipx: \
__asm { lea esi, BGCHR16[esi+ebp] } \
bg16_##label##_flip: \
__asm { cld } \
bg16_##label##_out: \
__asm { mov bh, 16 } \
__asm { shl bl, 4 } \
bg16_##label##_outlp: \
__asm { lodsb } \
__asm { or al, bl } \
__asm { and ax, 00ffh } \
__asm { je bg16_##label##_outed } \
__asm { test ax, 000fh } \
__asm { mov ax, word ptr TextPal[eax*2] } \
__asm { jne bg16_##label##_outcont } \
__asm { test byte ptr (Text_TrFlag+1)[edi], 2 } \
__asm { jne bg16_##label##_outed } \
bg16_##label##_outcont: \
__asm { mov word ptr (BG_LineBuf+2)[edi*2], ax } \
__asm { or byte ptr (Text_TrFlag+1)[edi], 2 } \
bg16_##label##_outed: \
__asm { inc edi } \
__asm { dec bh } \
__asm { jne bg16_##label##_outlp } \
__asm { add cl, 2 } \
__asm { and cl, 7fh } \
__asm { sub ebx, 10000h } \
__asm { jns bg16_##label##_linelp }
#define BG_DrawLineMcr8_ng(label, bgtop, scrx, scry) \
__asm { mov edx, scry } \
__asm { add edx, VLINEBG } \
__asm { sub edx, BG_VLINE } \
__asm { mov ebp, edx } \
__asm { and ebp, 7 } \
__asm { shl bp, 3 } \
__asm { and edx, 01f8h } \
__asm { shl edx, 4 } \
__asm { add dx, bgtop } \
__asm { mov eax, scrx } \
__asm { sub eax, BG_HAdjust } \
__asm { mov ecx, eax } \
__asm { and eax, 7 } \
__asm { xor al, 15 } \
__asm { mov edi, eax } \
__asm { and ecx, 01f8h } \
__asm { shr cx, 2 } \
__asm { mov ebx, TextDotX } \
__asm { shl ebx, 13 } \
bg8_ng_##label##_linelp: \
__asm { movzx esi, word ptr BG[ecx+edx] } \
__asm { mov bx, si } \
__asm { and si, 0ff00h } \
__asm { shr si, 2 } \
__asm { cmp bl, 40h } \
__asm { jc bg8_ng_##label##_flipx } \
__asm { js bg8_ng_##label##_fxflipy } \
__asm { jge bg8_ng_##label##_fxflipx } \
__asm { add esi, offset BGCHR8 + 00000038h } \
__asm { sub esi, ebp } \
__asm { jmp bg8_ng_##label##_flip } \
bg8_ng_##label##_fxflipy: \
__asm { add esi, offset BGCHR8 + 0000003fh } \
__asm { sub esi, ebp } \
__asm { std } \
__asm { jmp bg8_ng_##label##_out } \
bg8_ng_##label##_fxflipx: \
__asm { lea esi, BGCHR8[esi+ebp+7] } \
__asm { std } \
__asm { jmp bg8_ng_##label##_out } \
bg8_ng_##label##_flipx: \
__asm { lea esi, BGCHR8[esi+ebp] } \
bg8_ng_##label##_flip: \
__asm { cld } \
bg8_ng_##label##_out: \
__asm { mov bh, 8 } \
__asm { shl bl, 4 } \
bg8_ng_##label##_outlp: \
__asm { lodsb } \
__asm { and ax, 000fh } \
__asm { je bg8_ng_##label##_outed } \
__asm { or al, bl } \
__asm { mov ax, word ptr TextPal[eax*2] } \
__asm { mov word ptr (BG_LineBuf+2)[edi*2], ax } \
__asm { or byte ptr (Text_TrFlag+1)[edi], 2 } \
bg8_ng_##label##_outed: \
__asm { inc edi } \
__asm { dec bh } \
__asm { jne bg8_ng_##label##_outlp } \
__asm { add cl, 2 } \
__asm { and cl, 7fh } \
__asm { sub ebx, 10000h } \
__asm { jns bg8_ng_##label##_linelp }
#define BG_DrawLineMcr16_ng(label, bgtop, scrx, scry) \
__asm { mov edx, scry } \
__asm { add edx, VLINEBG } \
__asm { sub edx, BG_VLINE } \
__asm { mov ebp, edx } \
__asm { and ebp, 15 } \
__asm { shl bp, 4 } \
__asm { and edx, 03f0h } \
__asm { shl edx, 3 } \
__asm { add dx, bgtop } \
__asm { mov eax, scrx } \
__asm { sub eax, 0/*BG_HAdjust*/ } \
__asm { mov ecx, eax } \
__asm { and eax, 15 } \
__asm { xor al, 15 } \
__asm { mov edi, eax } \
__asm { and ecx, 03f0h } \
__asm { shr cx, 3 } \
__asm { mov ebx, TextDotX } \
__asm { shl ebx, 12 } \
bg16_ng_##label##_linelp: \
__asm { movzx esi, word ptr BG[ecx+edx] } \
__asm { mov bx, si } \
__asm { and si, 0ff00h } \
__asm { cmp bl, 40h } \
__asm { jc bg16_ng_##label##_flipx } \
__asm { js bg16_ng_##label##_fxflipy } \
__asm { jge bg16_ng_##label##_fxflipx } \
__asm { add esi, offset BGCHR16 + 000000f0h } \
__asm { sub esi, ebp } \
__asm { jmp bg16_ng_##label##_flip } \
bg16_ng_##label##_fxflipy: \
__asm { add esi, offset BGCHR16 + 000000ffh } \
__asm { sub esi, ebp } \
__asm { std } \
__asm { jmp bg16_ng_##label##_out } \
bg16_ng_##label##_fxflipx: \
__asm { lea esi, BGCHR16[esi+ebp+15] } \
__asm { std } \
__asm { jmp bg16_ng_##label##_out } \
bg16_ng_##label##_flipx: \
__asm { lea esi, BGCHR16[esi+ebp] } \
bg16_ng_##label##_flip: \
__asm { cld } \
bg16_ng_##label##_out: \
__asm { mov bh, 16 } \
__asm { shl bl, 4 } \
bg16_ng_##label##_outlp: \
__asm { lodsb } \
__asm { and ax, 000fh } \
__asm { je bg16_ng_##label##_outed } \
__asm { or al, bl } \
__asm { mov ax, word ptr TextPal[eax*2] } \
__asm { mov word ptr (BG_LineBuf+2)[edi*2], ax } \
__asm { or byte ptr (Text_TrFlag+1)[edi], 2 } \
bg16_ng_##label##_outed: \
__asm { inc edi } \
__asm { dec bh } \
__asm { jne bg16_ng_##label##_outlp } \
__asm { add cl, 2 } \
__asm { and cl, 7fh } \
__asm { sub ebx, 10000h } \
__asm { jns bg16_ng_##label##_linelp }
struct {
WORD sprite_posx;
WORD sprite_posy;
WORD sprite_ctrl;
BYTE sprite_ply;
BYTE dummy;
} SPRITECTRLTBL;
#define Sprite_DrawLineMcr(label, pri) \
__asm { mov ebp, TextDotX } \
__asm { add ebp, 16 } \
__asm { mov edx, 127*8 } \
spline_##label##_lp: \
__asm { mov al, Sprite_Regs[edx].sprite_ply } \
__asm { and al, 3 } \
__asm { cmp al, pri } \
__asm { je spline_##label##_plyhit } \
spline_##label##_lpcnt: \
__asm { sub dx, 8 } \
__asm { jns spline_##label##_lp } \
__asm { jmp spline_##label##_ed } \
spline_##label##_plyhit: \
__asm { movzx edi, Sprite_Regs[edx].sprite_posx } \
__asm { add edi, BG_HAdjust } \
__asm { and di, 03ffh } \
__asm { cmp edi, ebp } \
__asm { jnc spline_##label##_lpcnt } \
__asm { movzx eax, Sprite_Regs[edx].sprite_posy } \
__asm { and ax, 03ffh } \
__asm { sub eax, VLINEBG } \
__asm { add eax, BG_VLINE } \
__asm { neg eax } \
__asm { add eax, 16 } \
__asm { jnc spline_##label##_lpcnt } \
__asm { shl al, 4 } \
__asm { movzx esi, Sprite_Regs[edx].sprite_ctrl } \
__asm { mov bx, si } \
__asm { shl si, 8 } \
__asm { cmp bh, 40h } \
__asm { jc spline_##label##_flipx } \
__asm { js spline_##label##_fxflipy } \
__asm { jge spline_##label##_fxflipx } \
__asm { xor al, 0f0h } \
spline_##label##_flipx: \
__asm { lea esi, BGCHR16[esi + eax] } \
__asm { cld } \
spline_##label##_out: \
__asm { shl bh, 4 } \
__asm { mov ecx, 16 } \
spline_##label##_outlp: \
__asm { lodsb } \
__asm { and ax, 000fh } \
__asm { je spline_##label##_trans } \
__asm { or al, bh } \
__asm { cmp word ptr BG_PriBuf[edi*2], dx } \
__asm { jc spline_##label##_trans } \
__asm { mov ax, word ptr TextPal[eax*2] } \
__asm { mov word ptr BG_LineBuf[edi*2], ax } \
__asm { or byte ptr (Text_TrFlag)[edi], 2 } \
__asm { mov word ptr BG_PriBuf[edi*2], dx } \
spline_##label##_trans: \
__asm { inc edi } \
__asm { loop spline_##label##_outlp } \
__asm { jmp spline_##label##_lpcnt } \
spline_##label##_fxflipy: \
__asm { xor al, 0f0h } \
spline_##label##_fxflipx: \
__asm { lea esi, BGCHR16[esi + eax + 15] } \
__asm { std } \
__asm { jmp spline_##label##_out } \
spline_##label##_ed:
Loaded 100 of 156 files, more files were not shown because too many files have changed in this diff. Show more