![見出し画像](https://assets.st-note.com/production/uploads/images/140843417/rectangle_large_type_2_e00d04fc922b10da2e70816f2ffa799c.png?width=1200)
SGDK学習メモ:No.8、SCROLLとWINDOWのVRAMアドレスが重複している場合の挙動を確認してみる
*以下SGDKは記述時点で最新版のSGDK 2.00 (january 2024)を使用しています
前々回、前回の補足事項です。
VRAM内のメモリマッピングは(ある程度)自由に変更が可能で、更に複数の項目に同じVRAM領域を割り当てることも可能です。
5. VRAM MAPPING
(中略)
Also, AREA can be overlapped. Therefore, TABLE can be commonly used by SCROLL screen and WINDOW for example.
今回はSCROLL BとWINDOWに同じVRAMアドレスを割り当てた場合の挙動を確認してみます。
正直想像通りではありますが、実際に試してみたということで。文字に起こしてみるとちょっとまどろっこしいです。
SCROLL BとWINDOWに同じVRAMアドレスを割り当て、それらに背景画像(タイル)をセットしてみる
以下はSGDKデフォルト時のVRAMマッピングです。
![](https://assets.st-note.com/img/1715841975525-0aLuDssaYC.png)
今回SCROLL BとWINDOWに同じアドレスを設定します。
![](https://assets.st-note.com/img/1715842170745-tPYZlTZIJy.png)
VDP_setWindowAddress ( 0xC000 )
を実行しています
この状態でSCROLL BとWINDOWに背景用の画像(タイル)をセットしてみます。
前々回は画面上部にWINDOWを表示(横分割)したので、今回は画面左側(縦分割)を試します。
![](https://assets.st-note.com/img/1715842354363-tthkBETIOL.png?width=1200)
SCROLL Bに_(アンダースコア)、A、B、Cをセットした状態、
この時点でWINDOWには何も行っていません
![](https://assets.st-note.com/img/1715842895046-0mMiUmujc0.png?width=1200)
WINDOWの表示に必要な表示位置と表示(セル)数をセット"前"にも関わらず
WINDOWに設定したタイルが表示されます、
今回SCROLL BとWINDOWはアドレスが同じため
0~3がWINDOWではなくSCROLL Bとして表示されています
![](https://assets.st-note.com/img/1715843277836-uXss5IPF61.png)
WINDOWで指定したタイル("0-3")で上書きされたので、
重ね合わせ処理は行われていません
(通常なら0、2の下に存在するアンダースコアが存在しない)
![](https://assets.st-note.com/img/1715843488588-8BOC8KRRPc.png?width=1200)
具体的にはVDP_setWindowHPos(FALSE, 2)
を実行していますが上図では判別できません
![](https://assets.st-note.com/img/1715843645527-hFDFiLYQ0s.png?width=1200)
縦分割したWINDOWの表示は行われます、
WINDOWとSCROLL Bの左はじに
同じタイルが表示されています
![](https://assets.st-note.com/img/1717716735408-c1IciwOSMR.png)
優先順位は標準のままなので
WINDOW(SCROLL A) > SCROLL Bの状態、
上図の左側の"3"はWINDOWなので
SCROLL Bの"B"より優先的(上)に表示されています
今回のソースコードです。
#include <genesis.h>
//VRAMアドレス
#define HSCROLL_TABLE_ADDR 0xA800
#define SPRITE_LIST_ADDR 0xAC00
#define WINDOW_ADDR 0xB000
#define BGA_ADDR 0xC000
#define BGB_ADDR 0xE000
static const int sciSlash = 0x05AF; //word"/" , 1455
static const int sciA = 0x05C1; //word"A" , 1473
static const int sciOne = 0x05B0; //word"1" , 1456
static const int sciComma = 0x05AC; //word"," , 1452
static const int sciDot = 0x05AE; //word"." , 1454
static const int sciUScore = 0x05DF; //word"_" , 1503
static const int sciVBar = 0x05FC; //word"|" , 1532
s16 currentScreenX=0;
s16 currentScreenY=0;
//背景初期化
//BG_Bの表示範囲に値を埋める
void bgInit(){
//BG_B , "_"を敷きつめる
VDP_fillTileMapRect(BG_B,TILE_ATTR_FULL(PAL0,FALSE,FALSE,FALSE,sciUScore),0,0,39,27);
//BG_B,A(右端、垂直)とB(下部、水平)とC(AとBの交差点)を置く
VDP_fillTileMapRect(BG_B,TILE_ATTR_FULL(PAL1,FALSE,FALSE,FALSE,sciA),39,0,1,27);
VDP_fillTileMapRect(BG_B,TILE_ATTR_FULL(PAL1,FALSE,FALSE,FALSE,sciA+1),0,27,39,1);
VDP_setTileMapXY(BG_B,TILE_ATTR_FULL(PAL1,FALSE,FALSE,FALSE,sciA+2),39,27);
}
//VDP アドレスログ出力(デバッグ用)
void logVramAddresses(){
kprintf("VDP_getBGAAddress(): %x,(%u)",VDP_getBGAAddress(),VDP_getBGAAddress());
kprintf("VDP_getBGBAddress(): %x,(%u)",VDP_getBGBAddress(),VDP_getBGBAddress());
kprintf("VDP_getWindowAddress(): %x,(%u)",VDP_getWindowAddress(),VDP_getWindowAddress());
kprintf("VDP_getSpriteListAddress(): %x,(%u)",VDP_getSpriteListAddress(),VDP_getSpriteListAddress());
kprintf("VDP_getHScrollTableAddress(): %x,(%u)",VDP_getHScrollTableAddress(),VDP_getHScrollTableAddress());
}
//VDP アドレスセット(未使用)
void setVramAddresses(){
VDP_setBGBAddress ( BGB_ADDR );
VDP_setBGAAddress ( BGA_ADDR );
VDP_setWindowAddress ( WINDOW_ADDR );
VDP_setSpriteListAddress ( SPRITE_LIST_ADDR );
VDP_setHScrollTableAddress( HSCROLL_TABLE_ADDR );
}
//キーイベント(コールバック)
void myJoyHandler( u16 joy, u16 changed, u16 state)
{
if (joy == JOY_1){
//Aボタン
if (state & BUTTON_A){
//WINDOW(BG_Aの一部)に0~3をセット
VDP_setTileMapXY(WINDOW,TILE_ATTR_FULL(PAL3,FALSE,FALSE,FALSE,sciOne),0,0);
VDP_setTileMapXY(WINDOW,TILE_ATTR_FULL(PAL3,FALSE,FALSE,FALSE,sciOne+1),0,27);
VDP_setTileMapXY(WINDOW,TILE_ATTR_FULL(PAL3,FALSE,FALSE,FALSE,sciOne+2),3,0);
VDP_setTileMapXY(WINDOW,TILE_ATTR_FULL(PAL3,FALSE,FALSE,FALSE,sciOne+3),3,27);
}
//Bボタン
if (state & BUTTON_B){
//WINDOWをセット
//縦は2CELL単位の指定となる = 2だと4CELL分がWINDOWになる
VDP_setWindowHPos(FALSE, 2);
}
//Cボタン
if (state & BUTTON_C){
}
//Xボタン
if (state & BUTTON_X){
}
//Yボタン
if (state & BUTTON_Y){
}
//スタートボタン
if (state & BUTTON_START){
}
}
}
//キーイベント(VBlankごと)
static void handleInput()
{
u16 value = JOY_readJoypad(JOY_1);
if (value & BUTTON_UP){
currentScreenX++;
}
if (value & BUTTON_DOWN){
currentScreenX--;
}
if (value & BUTTON_RIGHT){
currentScreenY++;
}
if (value & BUTTON_LEFT){
currentScreenY--;
}
// VDP_setHorizontalScrollVSync (BG_A,currentScreenY);
VDP_setHorizontalScrollVSync(BG_B,currentScreenY);
// VDP_setVerticalScrollVSync(BG_A,currentScreenX);
VDP_setVerticalScrollVSync(BG_B,currentScreenX);
}
// main
int main()
{
JOY_init();
JOY_setEventHandler( &myJoyHandler );
kprintf("*** 0:vram address bofore changed");
logVramAddresses();
//VRAMのアドレスをマッピングを変更する
//WINDOWにSCROLL Bと同じ 0xC000 をセット
VDP_setWindowAddress ( 0xC000 );
kprintf("*** 2:vram address after changed");
logVramAddresses();
bgInit();
while(1)
{
handleInput();
SYS_doVBlankProcess();
}
return (0);
}
【了】