ハッシュタグ(2019/8/18)
- あいざっくとむ(Izk_tom)
- きもあん(kimoanman)
- くろいひとけん(Ken_in_black)
- さぶろう(SBRSNPI)
- しょーご(shogonishimoto)
- すーぱーたーぼ(SuperturboZ)
- たいにーやろう(tiny_yarou)
- たなむ(tanam1972)
- まえだ(hiropapa00)
- ぽいぽい(poipoi_007)
>zcc +pv1000 main.c -create-app上記コマンドでは暗黙的に以下がリンクされています。
main.c pv1000_crt0.asm lores.asm font.asm16KB ROM(0000-3FFF)のメモリーマップは以下になります。
0000-01FF CRT0 0200-03FF LORES 0400-0FFF FONTS 1000-3FFF MAIN32KB ROM(0000-7FFF)のメモリーマップは以下になります。
0000-01FF CRT0 0200-03FF LORES 0400-0FFF FONTS 1000-7FFF MAINLORES(0a-1f)とFONTS(20-7f)とPCG(e0-ff)は、RGBで合計32バイト使ってキャラクタ定義します。
N/A(8bytes) R (8bytes) G (8bytes) B (8bytes)VRAMにキャラクタ番号(00-ff)を描くと表示されます。 RAMのメモリーマップは以下になります。
B800-BAFF VRAM BB00-BBFF RAM BC00-BFFF PCGJOYPAD入力やPSG出力はEnri's Home PAGEを参考に、I/Oを叩いたらゲームつくれると思います。 http://www43.tok2.com/home/cmpslv/Pv1000/EnrPV1.htm
ゲームプログラマになる前に覚えておきたい技術
http://www.shuwasystem.co.jp/support/7980html/2118.html
サンプルプログラムの荷物君をz88dkでビルドしてPV-1000で動かしてみます。
>zcc +pv1000 main.c -create-app
main.c
/* Nimotsu Kun for PV-1000 by tanam [2019] */ #include "games.h" typedef int bool; typedef int Object; typedef unsigned char u8; typedef unsigned short u16; #define true 1 #define false 0 #define KEY_UP1 MOVE_UP #define KEY_DOWN1 MOVE_DOWN #define KEY_LEFT1 MOVE_LEFT #define KEY_RIGHT1 MOVE_RIGHT #define KEY_A MOVE_FIRE1 #define KEY_B MOVE_FIRE2 unsigned char *screen=0xB800; u16 game[224]; /* #壁 _空間 .ゴール oブロック p人 */ const char* gStageData = "\ ########\n\ # .. p #\n\ # oo #\n\ # #\n\ ########\n\ \n\ 0\ ###### \n\ #. # \n\ # o o # \n\ # op# # \n\ # # # \n\ #.###.# \n\ ### ### 0"; #define gStageWidth 8 #define gStageHeight 7 enum OBJ { OBJ_SPACE, OBJ_WALL, OBJ_GOAL, OBJ_BLOCK, OBJ_BLOCK_ON_GOAL, OBJ_MAN, OBJ_MAN_ON_GOAL, OBJ_UNKNOWN, }; Object state[56]; void screen_set_char(u8 xts, u8 yts, u8 xte, u8 yte, u16 *map) { int i, j, k; k=0; for (i = 0; i < 24; i++) for (j = 0; j < 32; j++) if (j > xts && j < xte && i > yts && i < yte) screen[(i+1)*32+j+1]=map[8*(i-1)+j-xts-1]; return; } /* 関数プロトタイプ */ void initialize( Object* state, char* stageData ); void draw( Object* state, int w, int h ); int update( Object* state, u16 input, int w, int h ); bool checkClear( Object* state, int w, int h ); int main(){ int stage; clg(); for (stage=0; stage<2; stage++) { RESET: initialize( state, gStageData+stage*63); /* ステージ初期化 */ /* メインループ */ while ( true ){ /* まず描画 */ draw( state, gStageWidth, gStageHeight ); /* クリアチェック */ if ( checkClear(state, gStageWidth, gStageHeight ) ){ break; /* クリアチェック */ } /* 更新 */ if (-1 == update( state, joystick(0), gStageWidth, gStageHeight )){ goto RESET; } } } return 0; } void initialize( Object* state, char* stageData ){ const char* d = stageData; /* 読み込みポインタ */ int x = 0; int y = 0; while ( *d != '0' ){ /* NULL文字でない間 */ Object t; /* 特に意味はないが使う回数が多い変数に私は良くtを使う。temporaryの略。たぶんよくない習慣だが、無駄に長い名前にして読みにくいのも困り物だろう。 */ switch ( *d ){ case '#': t = OBJ_WALL; break; case ' ': t = OBJ_SPACE; break; case 'o': t = OBJ_BLOCK; break; case 'O': t = OBJ_BLOCK_ON_GOAL; break; case '.': t = OBJ_GOAL; break; case 'p': t = OBJ_MAN; break; case 'P': t = OBJ_MAN_ON_GOAL; break; case '\n': x = 0; ++y; t = OBJ_UNKNOWN; break; /* 改行処理 */ default: t = OBJ_UNKNOWN; break; } ++d; if ( t != OBJ_UNKNOWN ){ /* 知らない文字なら無視するのでこのif文がある */ state[y * gStageWidth + x ] = t; /* 書き込み */ ++x; } } return; } void draw(Object* state, int width, int height ){ int x, y; char font[] = {' ', '#', '.', 'o', 'O', 'p', 'P'}; /* u16 font[] = {10,11,12,13,14,15,16}; /* Object列挙の順 */ for ( y = 0; y < height; ++y ){ for (x=0; x < width; ++x ){ Object o = state[ y * width + x ]; game[y * gStageWidth + x] = font[ o ]; } } screen_set_char(0, 0, 9, 8, game); } /* 第一引数はほかの関数ではstateとしているが、あまりに頻繁に使うので 短いsで済ませている。w,hもそれぞれwidth,heightである。 */ int update( Object* s, u16 input, int w, int h ){ /* 移動差分に変換(dはdifferenceでもdeltaでもお好きな方の略だと思って欲しい) */ int dx = 0; int dy = 0; int i = -1; int x, y, tx, ty, p, tp, tx2, ty2, tp2; switch ( input ){ case KEY_LEFT1: dx = -1; break; case KEY_RIGHT1: dx = 1; break; case KEY_UP1: dy = -1; break; case KEY_DOWN1: dy = 1; break; case KEY_A: return -1; } /* 人座標を検索 */ for ( i = 0; i < w * h; ++i ){ if ( s[ i ] == OBJ_MAN || s[ i ] == OBJ_MAN_ON_GOAL ){ break; } } x = i % w; /* xは幅で割ったあまり */ y = i / w; /* yは幅で割った商 */ /* 移動後座標(tに意味はない。ごめんなさい) */ tx = x + dx; ty = y + dy; /* 座標の最大最小チェック。外れていれば不許可 */ if ( tx < 0 || ty < 0 || tx >= w || ty >= h ){ return; } /* A.その方向が空白またはゴール。人が移動。 */ p = y*w + x; /* 人位置 */ tp = ty*w + tx; /* ターゲット位置(TargetPosition) */ if ( s[ tp ] == OBJ_SPACE || s[ tp ] == OBJ_GOAL ){ s[ tp ] = ( s[ tp ] == OBJ_GOAL ) ? OBJ_MAN_ON_GOAL : OBJ_MAN; /* ゴールならゴール上の人に */ s[ p ] = ( s[ p ] == OBJ_MAN_ON_GOAL ) ? OBJ_GOAL : OBJ_SPACE; /* もともとゴール上ならゴールに */ /* B.その方向が箱。その方向の次のマスが空白またはゴールであれば移動。 */ }else if ( s[ tp ] == OBJ_BLOCK || s[ tp ] == OBJ_BLOCK_ON_GOAL ){ /* 2マス先が範囲内かチェック */ tx2 = tx + dx; ty2 = ty + dy; if ( tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h ){ /* 押せない */ return; } tp2 = ( ty + dy )*w + ( tx + dx ); /* 2マス先 */ if ( s[ tp2 ] == OBJ_SPACE || s[ tp2 ] == OBJ_GOAL ){ /* 順次入れ替え */ s[ tp2 ] = ( s[ tp2 ] == OBJ_GOAL ) ? OBJ_BLOCK_ON_GOAL : OBJ_BLOCK; s[ tp ] = ( s[ tp ] == OBJ_BLOCK_ON_GOAL ) ? OBJ_MAN_ON_GOAL : OBJ_MAN; s[ p ] = ( s[ p ] == OBJ_MAN_ON_GOAL ) ? OBJ_GOAL : OBJ_SPACE; } } return 0; } /* ブロックのみがなければクリアしている。 */ bool checkClear(Object* s, int width, int height ){ int i; for (i = 0; i < width*height; ++i ){ if ( s[ i ] == OBJ_BLOCK ){ return false; } } return true; }
Visual Studio 2008でADAMem SDLをビルドしてみました。
ADAMem DOS and ADAMem SDL v1.81 - Page 2 - ColecoVision / Adam - AtariAge Forums
AdamemSDL.c
Mouse_Init (); // keyboardmode=(EmuMode)? 1:0; keyboardmode=0;
Z80IO.h
; //#if (__GNUC__ <= 3 && __GNUC__MINOR__ <= 4) \ // || (__GNUC__ >= 2 && __GNUC__MINOR__ >= 7) //#define FASTCALL __attribute__ ((regparm(3))) //#ifdef INLINE_MEM //#define INLINE_MEM_GNU //#endif //#else #define FASTCALL //#endif
SVI-328の拡張スロットに、MSXカートリッジをつなぐ方法を考えてみました。
以下の回路図から転記してみました。
http://www.hardwarebook.info/Spectravideo_SVI318/328_Expansion_Bus
http://d4.princess.ne.jp/msx/datas/slot.html
SVI-328 MSX PIN 1 +5V PIN45 +5V PIN 2 /CTRL2 NC PIN 3 +12V PIN48 +12V PIN 4 -12V PIN50 -12V PIN 5 /CTRL1 NC PIN 6 /WAIT PIN 7 /WAIT PIN 7 /RST PIN15 /RST PIN 8 CLK PIN42 CLK PIN 9 A15 PIN18 A15 PIN10 A14 PIN25 A14 PIN11 A13 PIN26 A13 PIN12 A12 PIN23 A12 PIN13 A11 PIN19 A11 PIN14 A10 PIN20 A10 PIN15 A9 PIN17 A9 PIN16 A8 PIN24 A8 PIN17 A7 PIN21 A7 PIN18 A6 PIN22 A6 PIN19 A5 PIN31 A5 PIN20 A4 PIN32 A4 PIN21 A3 PIN29 A3 PIN22 A2 PIN32 A2 PIN23 A1 PIN27 A1 PIN24 A0 PIN28 A0 PIN25 /RFSH PIN 6 /RFSH PIN26 /EXCSR NC PIN27 /M1 PIN 9 /M1 PIN28 /EXCSW NC PIN29 /WR PIN13 /WR PIN30 /MREQ PIN12 /MREQ PIN31 /IORQ PIN11 /IORQ PIN32 /RD PIN14 /RD PIN33 D0 PIN34 D0 PIN34 D1 PIN33 D1 PIN35 D2 PIN36 D2 PIN36 D3 PIN35 D3 PIN37 D4 PIN38 D4 PIN38 D5 PIN37 D5 PIN39 D6 PIN40 D6 PIN40 D7 PIN39 D7 PIN41 CSOUND PIN49 CSOUND PIN42 /INT PIN 8 /INT PIN43 /RAMDIS NC PIN44 /ROMDIS NC PIN45 /BK32 NC PIN46 /BK31 NC PIN47 /BK22 NC PIN48 /BK21 NC PIN49 GND PIN41 GND PIN50 GND PIN43 GND