original xkeropi-20101107
No files matched your search
@@ -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)
|
||||
@@ -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 $
|
||||
@@ -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
|
||||
@@ -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]
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 //
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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, };
|
||||
@@ -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
|
||||
@@ -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 $
|
||||
|
After Width: | Height: | Size: 526 B |
@@ -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 "
|
||||
};
|
||||
@@ -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..",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
@@ -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 ..",
|
||||
".. ..",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
@@ -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 */
|
||||
"................",
|
||||
"................",
|
||||
".. ....",
|
||||
".. . .... . ...",
|
||||
".. . .... . . ..",
|
||||
".. . ...... . ..",
|
||||
".. . . ..",
|
||||
".. .......... ..",
|
||||
".. . . ..",
|
||||
".. . ...... . ..",
|
||||
".. . ...... . ..",
|
||||
".. . ...... . ..",
|
||||
".. . ...... . ..",
|
||||
".. ..",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
@@ -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"
|
||||
};
|
||||
@@ -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.....",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
@@ -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 ...",
|
||||
"..... .....",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
@@ -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 */
|
||||
"................",
|
||||
"................",
|
||||
"..... .....",
|
||||
"... ...... ...",
|
||||
".. .......... ..",
|
||||
".. ...... ..",
|
||||
".. .. .. ..",
|
||||
".. .......... ..",
|
||||
".. .......... ..",
|
||||
".. .......... ..",
|
||||
".. .......... ..",
|
||||
".. .......... ..",
|
||||
"... ...... ...",
|
||||
"..... .....",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
@@ -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, };
|
||||
@@ -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
|
||||
@@ -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"
|
||||
};
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -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, };
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -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"
|
||||
};
|
||||
|
After Width: | Height: | Size: 662 B |
@@ -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 "
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
/* XPM */
|
||||
static char *nulldev[] = {
|
||||
/* width height ncolors chars_per_pixel */
|
||||
"16 16 2 1",
|
||||
/* colors */
|
||||
" c #9B9B9B",
|
||||
". c #C0C0C0",
|
||||
/* pixels */
|
||||
"................",
|
||||
"................",
|
||||
"... ...",
|
||||
".. .......... ..",
|
||||
".. . ...... . ..",
|
||||
".. .. .... .. ..",
|
||||
".. ... .. ... ..",
|
||||
".. .... ..... ..",
|
||||
".. ..... .... ..",
|
||||
".. ... .. ... ..",
|
||||
".. .. .... .. ..",
|
||||
".. . ...... . ..",
|
||||
".. .......... ..",
|
||||
"... ...",
|
||||
"................",
|
||||
"................"
|
||||
};
|
||||
|
After Width: | Height: | Size: 406 B |
@@ -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"
|
||||
};
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(®s, 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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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:
|
||||