commit e59d6da0a42c13b151d1e23dee56da207a37e966 Author: Zack Buhman Date: Thu Jan 5 21:46:12 2023 -0800 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ecc0e43 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +!/dts/* +dts/smpsys.o +*.iso +*.elf +*.bin +*.gch diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cbc659f --- /dev/null +++ b/Makefile @@ -0,0 +1,73 @@ +AFLAGS = -g --isa=sh2 --big +CFLAGS += -ffunction-sections -fshort-enums -ffreestanding -nostdlib +CFLAGS += -Wall -Werror -Wno-error=unused-but-set-variable -g -Og +CARCH = -m2 -mb + +TARGET = sh2-none-elf- +CC = $(TARGET)gcc +AS = $(TARGET)as +LD = $(TARGET)ld +OBJCOPY = $(TARGET)objcopy +OBJDUMP = $(TARGET)objdump + +all: main.iso + +define COPYELF + $(OBJCOPY) -I coff-sh -O elf32-sh \ + --rename-section .text=.text.$1 \ + $< $@ +endef + +sys_sec.o: dts/sys_sec.o + $(call COPYELF,sec) + +sys_are%.o: dts/sys_are%.o + $(call COPYELF,are) + +sys_init.o: dts/sys_init.o + $(call COPYELF,init) + +ID_OBJ += sys_id.o +ID_OBJ += sys_sec.o +ID_OBJ += sys_arej.o sys_aret.o sys_areu.o sys_aree.o +ID_OBJ += sys_init.o +ID_OBJ += dts/smpsys.o + +%.o: %.s + $(AS) $(AFLAGS) $< -o $@ + +%.o: %.S + $(CC) $(CFLAGS) -c $< -o $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ip.elf: $(ID_OBJ) + $(LD) --print-memory-usage -T ip.lds $^ -o $@ + +%.bin: %.elf + $(OBJCOPY) -O binary $< $@ + +MAIN_OBJ = main.o + +main.elf: $(MAIN_OBJ) + $(LD) --print-memory-usage -T sh2.lds $^ -o $@ + +main.iso: main.bin ip.bin + mkisofs \ + -sysid "SEGA SEGASATURN" \ + -volid "SAMPLE_GAME_TITLE" \ + -volset "SAMPLE_GAME_TITLE" \ + -publisher "SEGA ENTERPRISES, LTD." \ + -preparer "SEGA ENTERPRISES, LTD." \ + -G ip.bin \ + -o $@ \ + main.bin + +clean: + rm -f *.iso *.o *.bin *.elf + +.SUFFIXES: +.INTERMEDIATE: +.SECONDARY: +.PHONY: all clean dump diff --git a/dts/sega_sys.h b/dts/sega_sys.h new file mode 100644 index 0000000..81aac0a --- /dev/null +++ b/dts/sega_sys.h @@ -0,0 +1,154 @@ +/* + * 名称: システム プログラム + * + * ファイル名: sega_sys.h + * + * 目的: BOOT ROM のサービスルーチンを定義します。 + * + * (1) SCU 割り込みサービスルーチンの登録参照 + * (2) SH2 割り込みベクタの登録参照 + * (3) システムセマフォの操作 (BOOT ROM V0.90以降) + * (4) SCU 割り込みマスクの操作(BOOT ROM V0.90以降) + * (5) システムクロックの切替え(BOOT ROM V0.92以降) + * (6) SCU 割り込みルーチン優先度の変更(SCU2.1以降) + * (7) CD マルチプレーヤの起動実行(CD付きモデル用) + * (8) パワーオンクリアメモリの操作 (ROM V1.00以降) + * (9) MPEG チェック(完了復帰型) (ROM V1.00以降) + * + * sega_sys.libで関数を定義します。(Ver.2.01以降) + * + * 使用方法: + * + * void Vfunc(void) + * { + * // ... 実行文 ... // + * } + * + * extern void Hihdr(void); + * + * void test() + * { + * void (*tmp)(); + * Sint32 rep; + * Uint32 msk, clk, lval1; + * Uint8 p0; + * const Uint32 PriTab[32] = { + * 0x00f0ffff, 0x00e0fffe, 0x00d0fffc, 0x00c0fff8, + * 0x00b0fff0, 0x00a0ffe0, 0x0090ffc0, 0x0080ff80, + * 0x0080ff80, 0x0070fe00, 0x0070fe00, 0x0070fe00, + * 0x0070fe00, 0x0070fe00, 0x0070fe00, 0x0070fe00, + * 0x0070fe00, 0x0070fe00, 0x0070fe00, 0x0070fe00, + * 0x0070fe00, 0x0070fe00, 0x0070fe00, 0x0070fe00, + * 0x0070fe00, 0x0070fe00, 0x0070fe00, 0x0070fe00, + * 0x0070fe00, 0x0070fe00, 0x0070fe00, 0x0070fe00, + * }; + * + * SYS_SETUINT(0x40, Vfunc); // Vfunc() を VB-In 割込み用に登録 // + * tmp = SYS_GETUINT(0x41); // 現在の VB-Out ルーチン登録を参照 // + * SYS_SETUINT(0x41, 0); // VB-Out ルーチンの登録を消去 // + * + * SYS_SETSINT(0x42, Hihdr); // Hihdr() を HB-In ベクタに登録 // + * tmp = SYS_GETSINT(0x6e); // 現在の DIVU ベクタ登録を参照 // + * SYS_SETSINT(0x6e, 0); // DIVU ベクタを再初期化 // + * + * rep = SYS_TASSEM(0x5); // セマフォ 5 をテスト・アンド・セット // + * SYS_CLRSEM(0x5); // セマフォ 5 をクリア // + * + * SYS_SETSCUIM(0xfffffffe); // VB-In 割込みのみを許可に設定 // + * SYS_CHGSCUIM(0xfffffffc, 0); // VB-In, VB-Out を許可に変更 // + * SYS_CHGSCUIM(0xffffffff, 2); // VB-Out を不許可に変更 // + * msk = SYS_GETSCUIM; // 現在の SCU 割込みマスク値を参照 // + * + * SYS_CHGSYSCK(1); // システムクロックを28Mに切替え // + * clk = SYS_GETSYSCK; // 現在の システムクロック値を参照 // + * // 0: 26 MHz 1: 28 MHz // + * // 320/640 pix/H 352/704 pix/H // + * + * SYS_CHGUIPR(PriTab); // SCU割り込みルーチン優先度変更 // + * + * SYS_EXECDMP(); // CDマルチプレーヤ起動実行 // + * + * p0 = SYS_PCLRMEM; // パワーオンクリアメモリ先頭バイト // + * lval1 = *((Uint32*)&SYS_PCLRMEM+1); // と後半ロングワードを参照 // + * + * rep = SYS_CHKMPEG(0); // 引数は必ず 0. MANSYS.DOC の使用例 // + * // に従ってください // + * } + * + * // ... 別のファイル ... // + * #pragma interrupt(Hihdr) + * void Hihdr(void) + * { + * // ... 実行文 ... // + * } + * + * + * 日付: 1994/05/06 for BOOT 0.90,0.901,0.91 by T. S. + * 1994/07/16 for BOOT 0.92x,0.95 by T. S. + * 1994/07/29 for BOOT 0.96x,1.00 by T. S. + * 1994/08/31 how to exec CD multi-player + * 1994/09/21 for Ver.1.00 BOOT ROM + * 1995/03/31 MPEG check service + * 1995/09/26 sega_sys.lib (Ver.2.01) by M. M. + * + * バージョン: Ver.2.01 + * + */ + +#ifndef SEGA_SYS_H +#define SEGA_SYS_H + +/*********************************************************************** + * インクルードファイル + ***********************************************************************/ +#include "sega_xpt.h" + +/*********************************************************************** + * 処理マクロ + ***********************************************************************/ +#define SYS_SETUINT(_Num_, _Hdr_) \ + ((**(volatile void(**)(Uint32, void*))0x6000300)((_Num_), (_Hdr_))) +#define SYS_GETUINT(_Num_) \ + ((void*)(**(void(*(**)(Uint32))(Uint32))0x6000304)(_Num_)) + +#define SYS_SETSINT(_Num_, _Hdr_) \ + ((**(volatile void(**)(Uint32, void*))0x6000310)((_Num_), (_Hdr_))) +#define SYS_GETSINT(_Num_) \ + ((void*)(**(void(*(**)(Uint32))(Uint32))0x6000314)(_Num_)) + +#define SYS_TASSEM(_Num_) \ + ((**(volatile Uint32(**)(Uint32))0x6000330)(_Num_)) +#define SYS_CLRSEM(_Num_) \ + ((**(volatile void(**)(Uint32))0x6000334)(_Num_)) + +#define SYS_SETSCUIM(_MaskPat_) \ + ((**(volatile void(**)(Uint32))0x6000340)(_MaskPat_)) +#define SYS_CHGSCUIM(_AndMask_, _OrMask_) \ + ((**(volatile void(**)(Uint32, Uint32))0x6000344)((_AndMask_), (_OrMask_))) +#define SYS_GETSCUIM \ + (*(volatile Uint32*)0x6000348) + +#define SYS_CHGSYSCK(_CkMode_) \ + ((**(volatile void(**)(Uint32))0x6000320)(_CkMode_)) +#define SYS_GETSYSCK \ + (*(volatile Uint32*)0x6000324) + +#define SYS_CHGUIPR(_IprTab_) \ + ((**(volatile void(**)(Uint32*))0x6000280)(_IprTab_)) + +#define SYS_EXECDMP \ + (**(volatile void(**)(void))0x600026C) + +#define SYS_PCLRMEM \ + (*(volatile Uint8*)0x6000210) + +#define SYS_CHKMPEG(_dummy_) \ + ((**(volatile Sint32(**)(Sint32))0x6000274)(_dummy_)) + +/*********************************************************************** + * 関数の宣言 + ***********************************************************************/ +void SYS_CheckTrack(Sint32 tno); +void SYS_Exit(Sint32 code); + +#endif diff --git a/dts/sega_xpt.h b/dts/sega_xpt.h new file mode 100644 index 0000000..d2983e6 --- /dev/null +++ b/dts/sega_xpt.h @@ -0,0 +1,82 @@ +/* + * システム名称:ソフトウェアライブラリ + * + * モジュール記号名称:sega_xpt.h + * + * モジュール名称:ライブラリ共通ヘッダファイル + * + * 目的:(1)他マシン移植を簡単にするため + * (2)プログラムを解析しやすくするため + * + * 適用範囲:プログラミング全般(ライブラリ開発者、ライブラリ使用者の両方が使 + * 用できる) + * + * 前提条件:ここで宣言、定義している識別子と同じ意味の宣言、定義を他ファイル + * でしてはいけない。 + * + * AUTHOR:Ver1.00 N.T 1993/12/22 + * Ver1.01 N.T 1993/12/27 + * Ver1.02 N.T 1994/01/06 + * Ver1.03 N.T 1994/02/23 + * Ver1.04 N.T 1994/02/23 + * + * DATE:1994-07-29 + */ + + +#ifndef SEGA_XPT_H +#define SEGA_XPT_H + +/*****************************************************************************/ +/****************************** 基本データ型宣言 *****************************/ +/*****************************************************************************/ + +typedef unsigned char Uint8; /* 符号なし1バイト整数 */ +typedef signed char Sint8; /* 符号つき1バイト整数 */ +typedef unsigned short Uint16; /* 符号なし2バイト整数 */ +typedef signed short Sint16; /* 符号つき2バイト整数 */ +typedef unsigned long Uint32; /* 符号なし4バイト整数 */ +typedef signed long Sint32; /* 符号つき4バイト整数 */ +typedef float Float32; /* 4バイト実数 */ +typedef double Float64; /* 8バイト実数 */ + +typedef int Int; /* INT型(ツール用) */ + +typedef int Bool; /* 論理型(論理定数を値にとる) */ + +/*****************************************************************************/ +/********************************* 定数マクロ ********************************/ +/*****************************************************************************/ + +#ifndef NULL +#define NULL ((void *)0) /* NULL */ +#endif /* NULL */ + +/*****************************************************************************/ +/********************************** 列挙定数 *********************************/ +/*****************************************************************************/ + +enum BooleanLogic { /* 論理定数1(偽、真) */ + FALSE = 0, + TRUE = 1 +}; + +enum BooleanSwitch { /* 論理定数2(スイッチ) */ + OFF = 0, + ON = 1 +}; + +enum Judgement { /* 結果判定の定数(成功、失敗) */ + OK = 0, /* 成功 */ + NG = -1 /* 失敗 */ +}; + +/*****************************************************************************/ +/********************************* 処理マクロ ********************************/ +/*****************************************************************************/ + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) /* 最大値 */ +#define MIN(x, y) ((x) < (y) ? (x) : (y)) /* 最小値 */ +#define ABS(x) ((x) < 0 ? -(x) : (x)) /* 絶対値 */ + +#endif /* SEGA_XPT_H */ diff --git a/dts/smpsys.c b/dts/smpsys.c new file mode 100755 index 0000000..9a8a4d9 --- /dev/null +++ b/dts/smpsys.c @@ -0,0 +1,368 @@ +/* */ +/* アプリケーション初期化プログラムサンプル */ +/* V1.10 '94.11.11 S.U and T.S */ +/* */ +/* 動作タイミングと機能について: */ +/* ライセンス画面表示中に、不定になっている各種デバイス */ +/* 状態や、そのメモリのクリアなどを行ないます。 */ +/* 処理の所要時間は、0.1 秒程度かかります。 */ +/* 終了後、先読みしておいたプログラムの実行に移ります。 */ +/* その実行開始アドレスは APP_ENTRY に定義してください。 */ +/* */ +/* リンケージについて: */ +/* IPの sys_init.obj の直後にリンクしてください。 */ +/* プログラムをこのまま使用した場合、約360Hバイトに */ +/* なり、IPサイズは1000Hを越えますので注意して */ +/* ください。 */ +/* */ +/* プログラム変更時の注意: */ +/* main() の前に実行文を含む関数を追加しないでください。 */ +/* */ + +#include "sega_sys.h" + +/* 先読みしたプログラムの実行開始アドレス(メイン処理完了後にジャンプ)*/ +#define APP_ENTRY (0x06003000) + +/* デバイスを初期化するルーチン */ +static void vd1Comfil(void); /* VDP1 クリッピング初期化 */ +static void vd2Ramfil(void); /* VDP2 VRAMクリア */ +static void colRamfil(void); /* カラーRAMクリア */ +static void sndRamfil(Sint32); /* サウンドRAMクリア */ +static void scuDspInit(void); /* SCU DSP 初期化 */ +static void msh2PeriInit(void); /* マスタSH周辺モジュール初期化 */ +static void sndDspInit(void); /* サウンドDSPクリア */ + +/* その他サブルーチン */ +static void vbIrtn(void); /* VB-In 割込み処理 */ +static void vbOrtn(void); /* VB-Out 割込み処理 */ +static void syncVbI(void); /* VB-In 同期処理用 */ + +#ifndef __GNUC__ +static void memset_w(Sint16 *, Sint16, Sint32); /* ワード memset */ +static void memcpy_w(Sint16 *, Sint16 *, Sint32); /* ワード memcpy */ +static Sint16 *blkmfil_w(Sint16 *, Sint16, Sint32); + /* ワード・ブロックfill */ +static Sint32 *blkmfil_l(Sint32 *, Sint32, Sint32); + /* ロングワード・ブロックfill */ +#else +static void memset_w(volatile Sint16 *, Sint16, Sint32); +static void memcpy_w(volatile Sint16 *, Sint16 *, Sint32); +static void blkmfil_w(volatile Sint16 *, Sint16, Sint32); + /* ワード・ブロックfill */ +static void blkmfil_l(volatile Sint32 *, Sint32, Sint32); + /* ロングワード・ブロックfill */ +#endif + +/* 現時点の(ライセンス画面表示中)画面サイズに関する情報 */ +#define XRES (320) /* ライセンス画面の水平サイズ */ +#define SCLIP_UX (XRES-1) /* 〃 */ +#define SCLIP_UY_N (224-1) /* 〃 (NTSCの場合) */ +#define SCLIP_UY_P (256-1) /* 〃 (PALの場合) */ + +/* 処理対象デバイスのベースアドレス */ +#define SND_RAM ((volatile Sint32 *)0x25a00000) +#define VD1_VRAM ((volatile Sint16 *)0x25c00000) +#define VD1_REG ((volatile Sint16 *)0x25d00000) + /* VD2_VRAM は、ライセンス表示で使用中のVRAM領域を除く */ +#define VD2_VRAM ((volatile Sint32 *)0x25e08004) + /* COL_RAM は、ライセンス表示で使用中のカラーRAM領域を除く */ +#define COL_RAM ((volatile Sint16 *)0x25f00020) +#define VD2_REG ((volatile Sint16 *)0x25f80000) +#define SCSP_DSP_RAM ((volatile Sint16 *)0x25b00800) + +/* SMPCレジスタ */ +#define SMPC_REG(ofs) (*(volatile Uint8 *)(0x20100000+ofs)) + +/* SCUレジスタ */ +#define DSP_PGM_CTRL_PORT (*(volatile Sint32 *)0x25fe0080) +#define DSP_PGM_RAM_PORT (*(volatile Sint32 *)0x25fe0084) +#define DSP_DATA_RAM_ADRS_PORT (*(volatile Sint32 *)0x25fe0088) +#define DSP_DATA_RAM_DATA_PORT (*(volatile Sint32 *)0x25fe008c) + +/* SCSP サウンドRAMサイズレジスタ */ +#define SCSP_SNDRAMSZ (*(volatile Sint8 *)0x25b00400) + +/* SH2周辺モジュールレジスタ */ +#define MSH2_DMAC_SAR(ofs) (*(volatile Sint32 *)(0xffffff80 + ofs)) +#define MSH2_DMAC_DAR(ofs) (*(volatile Sint32 *)(0xffffff84 + ofs)) +#define MSH2_DMAC_TCR(ofs) (*(volatile Sint32 *)(0xffffff88 + ofs)) +#define MSH2_DMAC_CHCR(ofs) (*(volatile Sint32 *)(0xffffff8c + ofs)) +#define MSH2_DMAC_DRCR(sel) (*(volatile Sint8 *)(0xfffffe71 + sel)) +#define MSH2_DMAC_DMAOR (*(volatile Sint32 *)(0xffffffb0)) +#define MSH2_DIVU_CONT (*(volatile Sint32 *)(0xffffffb8)) + +/* メインの処理に関する情報 */ + /* 現在ライセンス表示中、16ビット1024色モードを使用 */ + /* VDP2のVRAMとカラーRAMは4回に分けてクリア */ + /* VRAMは1回に 20000H バイト(表示中部分を除く) */ + /* カラーRAMは1回に 200H バイト(表示中部分を除く) */ +#define MSETDIV (4) +#define BLKMSK_VD2_VRAM (0x1fffc) +#define BLKMSK_COL_RAM (0x001fe) + /* サウンドRAMは3手順でクリア */ +#define M68000_VECTBLSZ (0x00400/sizeof(Sint32)) +#define BLKMSK_SND_RAM (0x003fc) + /* サウンドDSP RAMサイズ */ +#define SCSP_DSP_RAMSZ (0x00400) + + /* 割込み処理に関する情報 */ +#define VBI_NUM (0x40) /* VBイン割込み番号 */ +#define VBO_NUM (0x41) /* VBアウト割込み番号 */ +#define VB_MASK (0x0003) /* SCU割込みマスク2つ分 */ + + /* スタティック変数 */ +static Sint16 yBottom, ewBotRight; +static Sint16 vdp1cmds[48]; +#ifndef __GNUC__ +/* static Sint16 vbIcnt = 0, sequence = 0; */ +static Sint16 vbIcnt = 0, sequence = 0; +static Sint32 *vramptr = VD2_VRAM; +static Sint16 *cramptr = COL_RAM; +#else +static volatile Sint16 vbIcnt = 0, sequence = 0; +static volatile Sint32 *vramptr = VD2_VRAM; +static volatile Sint16 *cramptr = COL_RAM; +#endif + +/* メイン処理 */ +void main(void) +{ + /* 注意:AUTO 変数をとると、APP_ENTRY のプログラムに */ + /* 制御が移るとき、スタックが若干無駄になる */ + + yBottom = (VD2_REG[2]&1)? SCLIP_UY_P: SCLIP_UY_N; + ewBotRight = ((XRES/8)<<9)+(yBottom); + /* 画面縦上限= 223(NTSC) or 255(PAL) */ + + SYS_SETUINT(VBI_NUM, vbIrtn); /* VBイン処理登録 */ + SYS_SETUINT(VBO_NUM, vbOrtn); /* VBアウト 〃 */ + SYS_CHGSCUIM( ~VB_MASK, 0); /* VB割込み2つ許可 */ + + vd1Comfil(); /* VDP1初期化 */ + for (sequence = 0; sequence < MSETDIV; sequence++) + { + syncVbI(); /* カラーRAMクリアのため同期 */ + colRamfil(); /* カラーRAMクリア */ + vd2Ramfil(); /* VDP2RAMクリア */ + sndRamfil(sequence); /* サウンドRAMクリア */ + } + + scuDspInit(); /* SCUのDSP初期化 */ + msh2PeriInit(); /* SH周辺モジュール〃 */ + sndDspInit(); /* サウンドDSP 〃 */ + + SYS_CHGSCUIM( -1, VB_MASK); /* VB割込み2つ禁止 */ + SYS_SETUINT(VBI_NUM, (void(*)())0 ); /* フック */ + SYS_SETUINT(VBO_NUM, (void(*)())0 ); /* 再初期化 */ + + ((void(*)())APP_ENTRY)(); /* 次の実行開始アドレス */ +} + +#ifndef __GNUC__ +static void memset_w(Sint16 *buf, Sint16 pattern, Sint32 size) +#else +static void memset_w(volatile Sint16 *buf, Sint16 pattern, Sint32 size) +#endif +{ + register Sint32 i; + + for (i = 0; i < size; i+= sizeof(Sint16)) { + *buf++ = pattern; + } +} + +#ifndef __GNUC__ +static void memcpy_w(Sint16 *dst, Sint16 *src, Sint32 size) +#else +static void memcpy_w(volatile Sint16 *dst, Sint16 *src, Sint32 size) +#endif +{ + register Sint32 i; + + for (i = 0; i < size; i+= sizeof(Sint16)) { + *dst++ = *src++; + } +} + +/* blkmfilは、区切りのいいアドレス範囲をmemsetするもの */ +#ifndef __GNUC__ +static Sint16 *blkmfil_w(Sint16 *buf, Sint16 pattern, Sint32 brkmsk) +#else +static void blkmfil_w(volatile Sint16 *buf, Sint16 pattern, Sint32 brkmsk) +#endif +{ + register Sint32 i; + +#ifndef __GNUC__ + i = (Sint32)buf & brkmsk; +#else + i = (volatile Sint32)buf & brkmsk; +#endif + for (; i <= brkmsk; i+= sizeof(Sint16)) { + *buf++ = pattern; + } +#ifndef __GNUC__ + return (buf); +#endif +} + +#ifndef __GNUC__ +static Sint32 *blkmfil_l(Sint32 *buf, Sint32 pattern, Sint32 brkmsk) +#else +static void blkmfil_l(volatile Sint32 *buf, Sint32 pattern, Sint32 brkmsk) +#endif +{ + register Sint32 i; + +#ifndef __GNUC__ + i = (Sint32)buf & brkmsk; +#else + i = (volatile Sint32)buf & brkmsk; +#endif + for (; i <= brkmsk; i+= sizeof(Sint32)) { + *buf++ = pattern; + } +#ifndef __GNUC__ + return (buf); +#endif +} + +/* VBインは、割込みでスタティック変数をインクリメントするのみ */ +static void vbIrtn(void) +{ + vbIcnt++; +} + +/* VBアウトは、割込みでVDP1レジスタをコントロールするのみ */ +static void vbOrtn(void) +{ +#ifndef __GNUC__ + register Sint16 *vdp1r; +#else + register volatile Sint16 *vdp1r; +#endif + /* イレースライトでフレームバッファをクリア */ + vdp1r = VD1_REG; + *vdp1r++ = 0x0; /* 1/60秒自動描画モード */ + *vdp1r++ = 0x0; + *vdp1r++ = 0x2; + *vdp1r++ = 0x0; /* イレースライトは透明色 */ + *vdp1r++ = 0x0; /* 〃 左上座標 */ + *vdp1r = ewBotRight; /* 〃 右下座標 */ +} + +/* VBI同期は、呼ばれると待ち、VBI直後に抜けて戻る */ +static void syncVbI(void) +{ + register Sint32 cur_cnt_value; + /* 待つのはカラーRAMクリアのため */ + cur_cnt_value = vbIcnt; + while (cur_cnt_value == vbIcnt); +} + +/* VDP1に、システムクリッピングとローカル座標を読ませる */ +static void vd1Comfil(void) +{ + register Sint16 *cmdbuf; + + memset_w((cmdbuf=vdp1cmds), 0, sizeof(vdp1cmds)); + cmdbuf[0] = 0x0009; + cmdbuf[10] = SCLIP_UX; + cmdbuf[11] = yBottom; + cmdbuf[16] = 0x000a; + cmdbuf[32] = 0x8000; + memcpy_w(VD1_VRAM, vdp1cmds, sizeof(vdp1cmds)); +} + +/* VDP2のRAMを、1/4ずつクリア */ +static void vd2Ramfil(void) +{ +#ifndef __GNUC__ + vramptr = blkmfil_l(vramptr, 0, BLKMSK_VD2_VRAM); +#else + blkmfil_l(vramptr, 0, BLKMSK_VD2_VRAM); +#endif +} + +/* カラーRAMを、1/4ずつクリア */ +static void colRamfil(void) +{ +#ifndef __GNUC__ + cramptr = blkmfil_w(cramptr, 0, BLKMSK_COL_RAM); +#else + blkmfil_w(cramptr, 0, BLKMSK_COL_RAM); +#endif +} + +/* サウンドRAMを、3手順でクリア */ +static void sndRamfil(Sint32 initstep) +{ +#ifndef __GNUC__ + register Sint32 *memptr; +#else + register volatile Sint32 *memptr; +#endif + + switch (initstep) { + case 0: + SMPC_REG(31) = 7; /* M68000を停止 */ + break; + case 1: + SCSP_SNDRAMSZ = 2; /* サウンドRAMサイズ設定 */ + /* サウンドRAM先頭400H */ + memptr = SND_RAM; /* (ベクタ)に400Hをフィル */ + blkmfil_l(memptr, 0x400, BLKMSK_SND_RAM); + *memptr = 0x0007fffc; /* SP初期値をセット */ + memptr += M68000_VECTBLSZ; + *memptr = 0x4e7160fc; /* アドレス400Hに NOPと */ + /* BRA @−2 命令を書込み */ + break; + case 2: + SMPC_REG(31) = 6; /* M68000起動(無限待ち) */ + break; + /* 備考: 1イントの間がある */ + } /* ため、SMPCステータスの */ +} /* セット/チェックを省略 */ + +static void msh2PeriInit(void) +{ + register Sint32 i, ofs, dummy; + + ofs = 0; + for(i = 0;i < 2; i++) + { /* DMAC各レジスタを初期化 */ + MSH2_DMAC_SAR(ofs) = 0x00000000; + MSH2_DMAC_DAR(ofs) = 0x00000000; + MSH2_DMAC_TCR(ofs) = 0x00000001; + dummy = MSH2_DMAC_CHCR(ofs); + MSH2_DMAC_CHCR(ofs) = 0x00000000; + MSH2_DMAC_DRCR(i) = 0x00; + ofs = 0x10; + } + dummy = MSH2_DMAC_DMAOR; + MSH2_DMAC_DMAOR = 0x00000000; + /* DIVU割込みを不許可 */ + MSH2_DIVU_CONT = 0x00000000; +} + +static void scuDspInit(void) +{ + register Sint32 i; + + DSP_PGM_CTRL_PORT = 0x0; /* DSP停止 */ + + for(i = 0; i < 256; i++) + DSP_PGM_RAM_PORT = 0xf0000000; /* END命令フィル */ + + for(i = 0; i < 256; i++){ /* DSP RAMクリア */ + DSP_DATA_RAM_ADRS_PORT = i; + DSP_DATA_RAM_DATA_PORT = 0x0; + } +} + +static void sndDspInit(void) +{ + memset_w(SCSP_DSP_RAM, 0, SCSP_DSP_RAMSZ); + /* サウンドDSP */ +} /* プログラム領域クリア */ diff --git a/dts/sys_aree.o b/dts/sys_aree.o new file mode 100644 index 0000000..3be4a1a Binary files /dev/null and b/dts/sys_aree.o differ diff --git a/dts/sys_arej.o b/dts/sys_arej.o new file mode 100644 index 0000000..ef55120 Binary files /dev/null and b/dts/sys_arej.o differ diff --git a/dts/sys_aret.o b/dts/sys_aret.o new file mode 100644 index 0000000..1d0ea6f Binary files /dev/null and b/dts/sys_aret.o differ diff --git a/dts/sys_areu.o b/dts/sys_areu.o new file mode 100644 index 0000000..b5b064e Binary files /dev/null and b/dts/sys_areu.o differ diff --git a/dts/sys_init.o b/dts/sys_init.o new file mode 100644 index 0000000..a680e8b Binary files /dev/null and b/dts/sys_init.o differ diff --git a/dts/sys_sec.o b/dts/sys_sec.o new file mode 100644 index 0000000..75a57ef Binary files /dev/null and b/dts/sys_sec.o differ diff --git a/ip.lds b/ip.lds new file mode 100644 index 0000000..7f26e0f --- /dev/null +++ b/ip.lds @@ -0,0 +1,19 @@ +OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh") +OUTPUT_ARCH(sh) + +MEMORY +{ + rom (arx) : ORIGIN = 0x06002000, LENGTH = 4M +} + +SECTIONS +{ + .text : ALIGN(4) + { + KEEP(*(.text.id)) + KEEP(*(.text.sec)) + KEEP(*(.text.are)) + KEEP(*(.text.init)) + KEEP(*(.text.smp)) + } > rom +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..1187366 --- /dev/null +++ b/main.c @@ -0,0 +1,15 @@ +#include "vdp2.h" + +void start(void) { + vdp2.reg.TVMD = ( TVMD__DISP | TVMD__BDCLMD | TVMD__LSMD__NON_INTERLACE + | TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320); + + vdp2.reg.BGON = 0; + + vdp2.reg.BKTAU = BKTAU__BKCLMD_SINGLE_COLOR | 0; + vdp2.reg.BKTAL = 0x4000; + + *((reg16 *)&vdp2.vram[0x8000]) = 31; // red + + while (1) {} +} diff --git a/sh2.lds b/sh2.lds new file mode 100644 index 0000000..400cd18 --- /dev/null +++ b/sh2.lds @@ -0,0 +1,39 @@ +OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh") +OUTPUT_ARCH(sh) +MEMORY +{ + work_ram_l : ORIGIN = 0x00200000, LENGTH = 1M + work_ram_h : ORIGIN = 0x06000000, LENGTH = 1M +} +SECTIONS +{ + . = 0x06000000; + + .text ALIGN(2) : SUBALIGN(2) + { + *(.text.start) + *(.text*) + } > work_ram_h + + .data ALIGN(4) : SUBALIGN(4) + { + *(.data) + } > work_ram_h + + .rodata ALIGN(4) : SUBALIGN(4) + { + *(.rodata) + } > work_ram_h + + .bss ALIGN(4) (NOLOAD) : SUBALIGN(4) + { + *(.bss) + } > work_ram_h + +} + +smpc = 0x00100000; +scsp = 0x05A00000; +vdp1 = 0x05C00000; +vdp2 = 0x05E00000; +scu = 0x05FE0000; diff --git a/sys_id.s b/sys_id.s new file mode 100644 index 0000000..c407dd9 --- /dev/null +++ b/sys_id.s @@ -0,0 +1,22 @@ + .section .text.id + + .ascii "SEGA SEGASATURN " /* 00: hardware identifier */ + .ascii "SEGA TP KAISHA-A" /* 10: maker ID */ + .ascii "999999999 V1.000" /* 20: product number, version */ + .ascii "19941122CD-1/1 " /* 30: release date, device information */ + .ascii "JTUE " /* 40: compatible area symbol */ + .ascii "J " /* 50: compatible peripheral */ + .ascii "GAME TITLE " /* 60: game title */ + .ascii " " /* 70: */ + .ascii " " /* 80: */ + .ascii " " /* 90: */ + .ascii " " /* A0: */ + .ascii " " /* B0: */ + .ascii " " /* C0: */ + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 /* D0: */ + .long 0x000012e8, 0x00000000, 0x00000000, 0x00000000 /* E0: IP SIZE, reserved, STACK-M, STACK-S */ + .long 0x06003000, 0x00000000, 0x00000000, 0x00000000 /* F0: Transfer destination address */ + /* Larger than (60020000H+IP SIZE), smaller than (6100000-4) */ + + /* IP SIZE of 0x1000 is manually calculated; this is coincidentally the + /* exact size of ip.bin as generated */ diff --git a/type.h b/type.h new file mode 100644 index 0000000..002e7c6 --- /dev/null +++ b/type.h @@ -0,0 +1,5 @@ +typedef volatile unsigned char reg8; +typedef volatile unsigned short reg16; +typedef volatile unsigned long reg32; +#define static_assert _Static_assert +#define offsetof __builtin_offsetof diff --git a/vdp2.h b/vdp2.h new file mode 100644 index 0000000..8cd898f --- /dev/null +++ b/vdp2.h @@ -0,0 +1,202 @@ +#include "type.h" + +/* memory offsets */ + +typedef unsigned char vdp2_vram[0x080000]; +typedef unsigned char vdp2_res0[0x080000]; +typedef unsigned char vdp2_cram[0x001000]; +typedef unsigned char vdp2_res1[0x07f000]; + +typedef struct vdp2_reg { + reg16 TVMD; /* TV SCREEN MODE */ + reg16 EXTEN; /* EXTERNAL SIGNAL ENABLE */ + reg16 TVSTAT; /* SCREEN STATUS */ + reg16 VRSIZE; /* VRAM SIZE */ + reg16 HCNT; /* H-COUNTER */ + reg16 VCNT; /* V-COUNTER */ + reg16 _res0; + reg16 RAMCTL; /* RAM CONTROL */ + reg16 CYCA0L; /* VRAM CYCLE PATTERN (BANK A0) */ + reg16 CYCA0U; /* VRAM CYCLE PATTERN (BANK A0) */ + reg16 CYCA1L; /* VRAM CYCLE PATTERN (BANK A1) */ + reg16 CYCA1U; /* VRAM CYCLE PATTERN (BANK A1) */ + reg16 CYCB0L; /* VRAM CYCLE PATTERN (BANK A0) */ + reg16 CYCB0U; /* VRAM CYCLE PATTERN (BANK A0) */ + reg16 CYCB1L; /* VRAM CYCLE PATTERN (BANK B1) */ + reg16 CYCB1U; /* VRAM CYCLE PATTERN (BANK B1) */ + reg16 BGON; /* SCREEN DISPLAY ENABLE */ + reg16 MZCTL; /* MOSAIC CONTROL */ + reg16 SFSEL; /* SPECIAL FUNCTION CODE SELECT */ + reg16 SFCODE; /* SPECIAL FUNCTION CODE */ + reg16 CHCTLA; /* CHARACTER CONTROL (NBG0, NBG1) */ + reg16 CHCTLB; /* CHARACTER CONTROL (NBG2, NBG3, RGB0) */ + reg16 BMPNA; /* BITMAP PALETTE NUMBER (NBG0, NBG1) */ + reg16 BMPNB; /* BITMAP PALETTE NUMBER (RGB0) */ + reg16 NBG0; /* PATTERN NAME CONTROL (NBG0) */ + reg16 NBG1; /* PATTERN NAME CONTROL (NBG1) */ + reg16 NBG2; /* PATTERN NAME CONTROL (NBG2) */ + reg16 NBG3; /* PATTERN NAME CONTROL (NBG2) */ + reg16 RGB0; /* PATTERN NAME CONTROL (RGB0) */ + reg16 PLSZ; /* PLANE SIZE */ + reg16 MPOFN; /* MAP OFFSET (NBG0~NBG3) */ + reg16 MPOFR; /* MAP OFFSET (ROTATION PARAMETER A,B) */ + reg16 MPABN0; /* MAP (NBG0, PLANE A,B) */ + reg16 MPCDN0; /* MAP (NBG0, PLANE C,D) */ + reg16 MPABN1; /* MAP (NBG1, PLANE A,B) */ + reg16 MPCDN1; /* MAP (NBG1, PLANE C,D) */ + reg16 MPABN2; /* MAP (NBG2, PLANE A,B) */ + reg16 MPCDN2; /* MAP (NBG2, PLANE C,D) */ + reg16 MPABN3; /* MAP (NBG3, PLANE A,B) */ + reg16 MPCDN3; /* MAP (NBG3, PLANE C,D) */ + reg16 MPABRA; /* MAP (ROTATION PARAMETER A, PLANE A,B) */ + reg16 MPCDRA; /* MAP (ROTATION PARAMETER A, PLANE C,D) */ + reg16 MPEFRA; /* MAP (ROTATION PARAMETER A, PLANE E,F) */ + reg16 MPGHRA; /* MAP (ROTATION PARAMETER A, PLANE G,H) */ + reg16 MPIJRA; /* MAP (ROTATION PARAMETER A, PLANE I,J) */ + reg16 MPKLRA; /* MAP (ROTATION PARAMETER A, PLANE K,L) */ + reg16 MPMNRA; /* MAP (ROTATION PARAMETER A, PLANE M,N) */ + reg16 MPOPRA; /* MAP (ROTATION PARAMETER A, PLANE O,P) */ + reg16 MPABRB; /* MAP (ROTATION PARAMETER B, PLANE B,B) */ + reg16 MPCDRB; /* MAP (ROTATION PARAMETER B, PLANE C,D) */ + reg16 MPEFRB; /* MAP (ROTATION PARAMETER B, PLANE E,F) */ + reg16 MPGHRB; /* MAP (ROTATION PARAMETER B, PLANE G,H) */ + reg16 MPIJRB; /* MAP (ROTATION PARAMETER B, PLANE I,J) */ + reg16 MPKLRB; /* MAP (ROTATION PARAMETER B, PLANE K,L) */ + reg16 MPMNRB; /* MAP (ROTATION PARAMETER B, PLANE M,N) */ + reg16 MPOPRB; /* MAP (ROTATION PARAMETER B, PLANE O,P) */ + reg16 SCXIN0; /* SCREEN SCROLL VALUE (NBG0, HORIZONTAL INTEGER PART) */ + reg16 SCXDN0; /* SCREEN SCROLL VALUE (NBG0, HORIZONTAL FRACTIONAL PART) */ + reg16 SCYIN0; /* SCREEN SCROLL VALUE (NBG0, VERTICAL INTEGER PART) */ + reg16 SCYDN0; /* SCREEN SCROLL VALUE (NBG0, VERTICAL FRACTIONAL PART) */ + reg16 ZMXIN0; /* COORDINATE INCREMENT (NBG0, HORIZONTAL INTEGER PART) */ + reg16 ZMXDN0; /* COORDINATE INCREMENT (NBG0, HORIZONTAL FRACTIONAL PART) */ + reg16 ZMYIN0; /* COORDINATE INCREMENT (NBG0, VERTICAL INTEGER PART) */ + reg16 ZMYDN0; /* COORDINATE INCREMENT (NBG0, VERTICAL FRACTIONAL PART) */ + reg16 SCXIN1; /* SCREEN SCROLL VALUE (NBG1, HORIZONTAL INTEGER PART) */ + reg16 SCXDN1; /* SCREEN SCROLL VALUE (NBG1, HORIZONTAL FRACTIONAL PART) */ + reg16 SCYIN1; /* SCREEN SCROLL VALUE (NBG1, VERTICAL INTEGER PART) */ + reg16 SCYDN1; /* SCREEN SCROLL VALUE (NBG1, VERTICAL FRACTIONAL PART) */ + reg16 ZMXIN1; /* COORDINATE INCREMENT (NBG1, HORIZONTAL INTEGER PART) */ + reg16 ZMXDN1; /* COORDINATE INCREMENT (NBG1, HORIZONTAL FRACTIONAL PART) */ + reg16 ZMYIN1; /* COORDINATE INCREMENT (NBG1, VERTICAL INTEGER PART) */ + reg16 ZMYDN1; /* COORDINATE INCREMENT (NBG1, VERTICAL FRACTIONAL PART) */ + reg16 SCXN2; /* SCREEN SCROLL VALUE (NBG2, HORIZONTAL) */ + reg16 SCYN2; /* SCREEN SCROLL VALUE (NBG2, VERTICAL) */ + reg16 SCXN3; /* SCREEN SCROLL VALUE (NBG3, HORIZONTAL) */ + reg16 SCYN3; /* SCREEN SCROLL VALUE (NBG3, VERTICAL) */ + reg16 ZMCTL; /* REDUCTION ENABLE */ + reg16 SCRCTL; /* LINE AND VERTICAL CELL SCROLL CONTROL (NBGO, NBG1) */ + reg16 VCSTAU; /* VERTICAL CELL SCROLL TABLE ADDRESS (NBGO, NBG1) */ + reg16 VCSTAL; /* VERTICAL CELL SCROLL TABLE ADDRESS (NBGO, NBG1) */ + reg16 LSTA0U; /* LINE SCROLL TABLE ADDRESS (NBG0) */ + reg16 LSTA0L; /* LINE SCROLL TABLE ADDRESS (NBG0) */ + reg16 LSTA1U; /* LINE SCROLL TABLE ADDRESS (NBG1) */ + reg16 LSTA1L; /* LINE SCROLL TABLE ADDRESS (NBG1) */ + reg16 LCTAU; /* LINE COLOR SCREEN TABLE ADDRESS */ + reg16 LCTAL; /* LINE COLOR SCREEN TABLE ADDRESS */ + reg16 BKTAU; /* BACK SCREEN TABLE ADDRESS */ + reg16 BKTAL; /* BACK SCREEN TABLE ADDRESS */ + reg16 RPMD; /* ROTATION PARAMETER MODE */ + reg16 RPRCTL; /* ROTATION PARAMETER READ CONTROL */ + reg16 KTCTL; /* COEFFICIENT TABLE CONTROL */ + reg16 KTAOF; /* COEFFICIENT TABLE ADDRESS OFFSET (ROTATION PARAMETER A, B) */ + reg16 OVPNRA; /* SCREEN OVER PATTERN NAME (ROTATION PARAMETER A) */ + reg16 OVPNRB; /* SCREEN OVER PATTERN NAME (ROTATION PARAMETER B) */ + reg16 RPTAU; /* ROTATION PARAMETER TABLE ADDRESS (ROTATION PARAMETER A,B) */ + reg16 RPTAL; /* ROTATION PARAMETER TABLE ADDRESS (ROTATION PARAMETER A,B) */ + reg16 WPSX0; /* WINDOW POSITION (W0, HORIZONTAL START POINT) */ + reg16 WPSY0; /* WINDOW POSITION (W0, VERTICAL START POINT) */ + reg16 WPEX0; /* WINDOW POSITION (W0, HORIZONTAL END POINT) */ + reg16 WPEY0; /* WINDOW POSITION (W0, VERTICAL END POINT) */ + reg16 WPSX1; /* WINDOW POSITION (W1, HORIZONTAL START POINT) */ + reg16 WPSY1; /* WINDOW POSITION (W1, VERTICAL START POINT) */ + reg16 WPEX1; /* WINDOW POSITION (W1, HORIZONTAL END POINT) */ + reg16 WPEY1; /* WINDOW POSITION (W1, VERTICAL END POINT) */ + reg16 WCTLA; /* WINDOW CONTROL (NBG0, NBG1) */ + reg16 WCTLB; /* WINDOW CONTROL (NBG2, NBG3) */ + reg16 WCTLC; /* WINDOW CONTROL (RGB0, SPRITE) */ + reg16 WCTLD; /* WINDOW CONTROL (PARAMETER WINDOW, COLOR CALC. WINDOW) */ + reg16 LWTA0U; /* LINE WINDOW TABLE ADDRESS (W0) */ + reg16 LWTA0L; /* LINE WINDOW TABLE ADDRESS (W0) */ + reg16 LWTA1U; /* LINE WINDOW TABLE ADDRESS (W1) */ + reg16 LWTA1L; /* LINE WINDOW TABLE ADDRESS (W1) */ + reg16 SPCTL; /* SPRITE CONTROL */ + reg16 SDCTL; /* SHADOW CONTROL */ + reg16 CRAOFA; /* COLOR RAM ADDRESS OFFSET (NBG0~NBG3) */ + reg16 CRAOFB; /* COLOR RAM ADDRESS OFFSET (RGB0, SPRITE) */ + reg16 LNCLEN; /* LINE COLOR SCREEN ENABLE */ + reg16 SFPRMD; /* SPECIAL PRIORITY MODE */ + reg16 CCCTL; /* COLOR CALCULATION CONTROL */ + reg16 SFCCMD; /* SPECIAL COLOR CALCULATION MODE */ + reg16 PRISA; /* PRIORITY NUMBER (SPRITE 0,1) */ + reg16 PRISB; /* PRIORITY NUMBER (SPRITE 2,3) */ + reg16 PRISC; /* PRIORITY NUMBER (SPRITE 4,5) */ + reg16 PRISD; /* PRIORITY NUMBER (SPRITE 6,7) */ + reg16 PRINA; /* PRIORITY NUMBER (NBG0, NBG1) */ + reg16 PRINB; /* PRIORITY NUMBER (NBG2, NBG3) */ + reg16 PRIR; /* PRIORITY NUMBER (RGB0) */ + reg16 _res1; + reg16 CCRSA; /* COLOR CALCULATION RATIO (SPRITE 0,1) */ + reg16 CCRSB; /* COLOR CALCULATION RATIO (SPRITE 2,3) */ + reg16 CCRSC; /* COLOR CALCULATION RATIO (SPRITE 4,5) */ + reg16 CCRSD; /* COLOR CALCULATION RATIO (SPRITE 6,7) */ + reg16 CCRNA; /* COLOR CALCULATION RATIO (NBG0, NBG1) */ + reg16 CCRNB; /* COLOR CALCULATION RATIO (NBG2, NBG3) */ + reg16 CCRR; /* COLOR CALCULATION RATIO (RGB0) */ + reg16 CCRLB; /* COLOR CALCULATION RATIO (LINE COLOR SCREEN, BACK SCREEN) */ + reg16 CLOFEN; /* COLOR OFFSET ENABLE */ + reg16 CLOFSL; /* COLOR OFFSET SELECT */ + reg16 COAR; /* COLOR OFFSET A (RED) */ + reg16 COAG; /* COLOR OFFSET A (GREEN) */ + reg16 COAB; /* COLOR OFFSET A (BLUE) */ + reg16 COBR; /* COLOR OFFSET B (RED) */ + reg16 COBG; /* COLOR OFFSET B (GREEN) */ + reg16 COBB; /* COLOR OFFSET B (BLUE) */ +} vdp2_reg; + +static_assert((sizeof (struct vdp2_reg)) == 0x120); + +struct vdp2 { + vdp2_vram vram; + vdp2_res0 _res0; + vdp2_cram cram; + vdp2_res1 _res1; + vdp2_reg reg; +}; + +static_assert((sizeof (struct vdp2)) == 0x180120); +static_assert((offsetof (struct vdp2, vram)) == 0x000000); +static_assert((offsetof (struct vdp2, cram)) == 0x100000); +static_assert((offsetof (struct vdp2, reg)) == 0x180000); + +extern struct vdp2 vdp2 __asm("vdp2"); + +/* register bits */ + +/* TVMD */ +#define TVMD__DISP (1 << 15) +#define TVMD__BDCLMD (1 << 8) // display back screen +#define TVMD__LSMD__NON_INTERLACE (0b00 << 6) +#define TVMD__LSMD__SINGLE_DENSITY (0b10 << 6) +#define TVMD__LSMD__DOUBLE_DENSITY (0b11 << 6) + +#define TVMD__VRESO__224 (0b00 << 4) +#define TVMD__VRESO__240 (0b01 << 4) +#define TVMD__VRESO__256 (0b10 << 4) + +#define TVMD__HRESO__NORMAL_320 (0b000 << 0) +#define TVMD__HRESO__NORMAL_352 (0b001 << 0) +#define TVMD__HRESO__HIRES_640 (0b010 << 0) +#define TVMD__HRESO__HIRES_704 (0b011 << 0) + +#define TVMD__HRESO__EXCLUSIVE_320 (0b100 << 0) +#define TVMD__HRESO__EXCLUSIVE_352 (0b101 << 0) +#define TVMD__HRESO__EXCLUSIVE_640 (0b110 << 0) +#define TVMD__HRESO__EXCLUSIVE_704 (0b111 << 0) + +/* TVSTAT */ +#define TVSTAT__VBLANK (1 << 3) + +/* BKTAU */ +#define BKTAU__BKCLMD_SINGLE_COLOR (0 << 15) +#define BKTAU__BKCLMD_PER_LINE (1 << 15)