正如世嘉土星的游戏是在1995年编写的

这是我在1995年开发Neversoft工作室的第一个游戏:Skeleton Warriors时写的一个文档。 这是我第一次不使用68K汇编语言的游戏。

周围时间拍的照片。 开发套件(“ Small Box”和ICE)在我右边。


游戏状态


以下文档简要描述了Sega Saturn的Skeleton Warriors代码的状态,还提到了许多尚需完成的方面。

需要该文档以便加快Dan,Ken和James对现成代码的熟悉,并向他们解释每个模块的目的以及它们之间的交互。 他还让我欣赏了这段代码的悲惨境地,并希望让我下定决心。

我还谈到了在程序中嵌入数据(.GOV和.GOB文件)的情况,以及将来的操作。

开发设备


我们的目标平台是Sega Saturn,它具有两个SH2 Risc微处理器和一个68000。只要我们仅使用Master SH2主处理器,在确定如何执行此操作时将使用辅助SH2从属。 68000用于控制声音芯片,我们不必为其编写代码,因为它将使用Sega提供的声音库。

该程序几乎完全用纯C语言编写。我们使用GNU SH2编译器来获取SH2输出汇编器。 代码中有几个SH2模块,主要只包含数据。 到目前为止,我还没有在SH2上写任何有意义的东西。

作为开发系统,我们使用PsyQ。 这不是标准的Sega开发系统,但是使用它的每个人都认为它是最好的。 替代方法是Sega所拥有的Cross Products创建的SNASM。 Sega提供的大多数代码示例都应在SNASM开发系统中运行,但可以轻松转换为PsyQ。

PsyQ系统由安装在PC中的SCSI接口卡,插入Saturn并连接电缆的盒带组成。 源代码在PC上编译并下载到土星程序,土星程序将在此启动。 可以从PC调试代码。


PsyQ开发系统

通信由驻留程序(PSYBIOS)控制,该驻留程序处理计算机之间的通信。 这使Saturn控制台可以从PC下载文件,就像从CD下载文件一样。 我们使用此功能下载每个级别的文件。

我的房间里有几个又大又大的抽屉,还有两台电脑。 两个框中较小的一个是E7000PC,它是内置的SH2仿真器。 如果PsyQ调试器没有停止程序,它将有助于弄清楚程序在哪里崩溃。 它对于跟踪对内存的写入也很有用,但是到目前为止,我几乎没有使用过此功能。

第二个大抽屉是一个叫做“小盒子”的东西(第一个“大盒子”大约是一个小冰箱的大小)。 本质上,它是Saturn,带有用于E7000和CD仿真器的附加接口。 在前面板上,它具有国家(地区)ID开关以及PAL和NTSC之间的开关。

第二台计算机内部是CD仿真器-大板,计算机的硬盘驱动器因此而假装成CD驱动器。 您可以在其中收集CD映像并进行实时仿真,以查看游戏在获得真实CD时的外观。 该仿真器或多或少都可以工作,尽管它存在一些问题,我们正在与世嘉合作。

图片

世嘉的开发套件本身

编译与链接


完成的程序的一般程序集由一个生成文件:MAKEFILE.MAK控制。 它包含整个项目的依赖关系和目标,包括编译.GOB和.GOV文件。

CCSH将各个C源代码模块(.C文件)编译为SH2对象模块(.OBJ)。 它首先调用名为CPPSH的GNU C预处理程序(位于C:\ GNUSH2 \ BIN中),然后调用CC1SH作为其输出以创建SH2汇编程序代码,最后调用ASSH(在C:\ PSYQ中)进行构建。转换为成品对象格式。

我们不使用C ++,因为有人告诉我它创建了巨大的目标文件。 但是,我没有和他一起工作,可以进行实验。

只需使用ASMSH将几个SH2汇编器文件(具有.S扩展名)直接收集到.OBJ文件中(这与ASSH不同,但是更复杂的宏汇编器)。 当前,它们仅用于嵌入数据,并且不包含与机器有关的代码。

可以将代码加载到其中的Saturn RAM分为两个1MB的块。 一个起价为06,000,000美元,另一个起价为002,000,000美元。 $ 00,200,000的块专门用于存储主角的图形。 程序代码以$ 06010000编写(前$ 10,000个字节用于系统空间,堆栈等)。

该代码与位置相关,并且可以在此特定地址($ 06010000)上运行,并且仅此而已。

使用PSYLINK程序将.OBJ文件链接在一起,以创建MAIN.CPE文件,该文件是带有小标题的可执行程序,可以使用RUN命令将其下载到Saturn。 PSYLINK使用TEST.LNK文件指示要包括的.OBJ文件以及将其放置在何处。

资料


游戏分为几个级别,许多级别使用相同的数据,但基本上每个级别它们都不同。 每个级别的所有数据都收集在两个巨大的.GOV和.GOB文件中。 (如果是地雷,则是MINE.GOV和MINE.GOB)。 GOV文件包含一个简短的标头,然后是应该在视频内存中的所有数据。 .GOB文件包含必须在RAM中的所有数据。

该级别由下面显示的数据文件的一部分组成。

.SSQ-Sprite音序器文件
.SBM-用于位背景的位图文件
.MAP-这两个地图都填充了符号背景。
.TIL-填充符号的背景的图块和调色板。
.PTH-道路点和触发器的数据。
.TEX-道路纹理。

.SSQ和.SBM文件是由我越来越不舒服的SEQ排序器创建的。 .MAP,.TIL,.PTH和.TEX文件是由越来越令人震惊的TULE地图编辑器Dan创建的。

使用ASMSH汇编程序将这些文件汇编为相应的.GOV和.GOB文件。 若要查看此操作,请参阅LEVEL.S和LEVEL1.S文件。 .GOV文件还包括特定级别的一些数据。

模组


TEST.S-没什么特别的,设置一些标签。

MAIN.C是程序的顶层。 它包含设备的初始化,级别设置,用于通过级别的代码以及实际上应放置在更合适的模块中的各种其他小元素。 其中有很多垃圾,因为最简单的方法是在此模块中添加新内容以进行快速测试。 包含来自CD或PC上文件服务器的启动代码。 包含用于启用或禁用TIMING颜色条的标志。

GFXLIB.C-用于访问设备和执行各种图形功能的各种过程。 几乎所有的文档都是由Dan从头开始编写的,通常效率很低。 如果您经常从这里使用该过程,那么最好看看它的作用并在代码中编写一个更快的版本。

但是,所有功能都可以正常工作,并为粗略的实现和测试提供了一个出色的框架。 谢谢丹,没有他就不可能。

SMP_PAD.C-从土星操纵杆读取数据的各种过程,非常依赖于设备。

GLOBALS.C-所有全局变量和几个常用函数。 使用全局变量是可接受的编程习惯。 但是,由于各种原因,SH2中全局变量的执行速度相当慢,因此随着时间的流逝,我可能会在必要时将零件转换为全局结构。 包含描述MANPATH状态的变量。

MAN.C-处理人员的移动和显示(Lightstar王子,Talyn,Guardian或Grimskull王子-玩家控制的角色)。 到目前为止,这主要是运动和与道路碰撞的逻辑。 另外,它为每个动作提供适当的动画。 还有很多工作要做。

OB.C-处理游戏中物体的移动和显示,尤其是敌人的物体,例如骷髅战士和小外星人。 游戏的主要部分在此处进行编程:敌人AI,基本动作和触发器触发。 数据结构尚未准备就绪,尤其是碰撞和动画问题尚未完全解决。 还有很多工作要做。

DATA.S-各种表格,目前主要是玩家主要角色的动画。

LAYER.C-具有视差的滚动背景。 更新符号背景和滚动位图。 还在雾层中滚动线(波浪效果)。 到目前为止,符号映射图层的表没有压缩就可以存储。 它们需要压缩为我用于Genesis版本的RLE格式。 如果我们早于索尼获得土星的开发系统,那么这项任务可以交给肯。

PAL.C-调色板。 您可以选择2048种颜色。 屏幕上的任何像素都可以是这些颜色之一。 我从逻辑上将调色板划分为八个256色调色板。 PAL.C包含用于初始化,准备和循环更改的代码。 它们还需要调光和更复杂的循环移位,以及亮度闪烁等。

BUL.C是一个原始系统,用于将炮弹(投掷剑,拳打手,从武器发射的火箭等)作为单独的对象进行处理。 对于更复杂的外壳使用,仍需要大量工作。 您还需要正确的碰撞和动画代码。

PAD.C是一个简单的模块,用于以更方便的格式存储操纵杆的状态。 存储按钮是否最近被按下以及是否现在被按下。

START.C-告诉第一级的一行,以方便在批处理文件中进行更改。

PANEL.C-撤回强弱连胜的简单程序。

PATH.C-绘制道路以及处理与道路碰撞的可怕程序。

MATH.C-简单的正弦,余弦和点旋转角度。

[更新]这是MAN.C的示例代码。 一切都严格地用代码编写,并引用全局数据结构Man。 代码中写的一堆数字。

/**************************************************************/ /* Trigger jumping if needed, also variable height jump logic */ Man_JumpTrigger() { if ( Man.JumpFudge ) { Man.JumpFudge--; } if ( Man.Mode != M_Crouch || Man_StandingRoom() ) // ok if not crouched, or there is headroom { if (Pad_Jump->Pressed) /* jump button pressed */ { if ((Man.Contact || (Man.Mode == M_Hang) || Man.JumpFudge) && Pad_Jump->Triggered && !Man.Blocking) /* and not already jumping */ { if (Man.Mode == M_Hang && Pad1.Down.Pressed) { Man.Contact=0; Man.Mode=M_Jump; Man.AnimBase = LS_Jumping; /* Change base anim to jumping */ Man_TriggerSeq(LS_Jump); /* start the jumping start anim */ Man.YV.f = 0x10000; /* and have no YV */ Man.Yi += 4; /* and have no YV */ } else { Pad_Jump->Triggered = 0; if ( !JetPacCheat ) Man.YV.f = -0x00080000; /* Initial jump speed */ else Man.YV.f = -0x00008000; // Initial speed in Jetpac mode Man.Contact = 0; /* not on the ground any more */ Man.JumpTime = 0; /* just started jumping */ Man.AnimBase = LS_Jumping; /* Change base anim to jumping */ Man_TriggerSeq(LS_Jump); /* start the jumping start anim */ Man.XV.f+=Man.FlyVel; if (Man.HangEnd && Man.Mode == M_Hang) // if hanging { // and on the end of a path Man.HangEnd = 0; Man.Xi += 12*Man.Facing; // the move past end of path Man.JumpTime = -3; // bit more fixed v jump time } Man.Mode = M_Jump; /* change mode to jumping */ } } else /* Already jumping */ { if (Man.JumpTime++ < MaxJumpTime) /* Still in initial jump period */ Man.YV.f -= 0x0005000; /* So can maintain jump YV */ } } else /* jump button not pressed */ { Man.JumpTime = MaxJumpTime+1; /* so can't alter YV again until landed */ } } } 

OB.C已成长为9,000行的庞大文件,其中包括游戏中单个对象的所有行为模式。 另外,代码中还写有大量数字,例如:

 Drop_Arac(S_Ob *pOb) { int t; if (pOb->Jump==1) { pOb->yv.f+=0x7fff; pOb->y.f+=pOb->yv.f; t=Path_GetYZ(pOb->xi,pOb->yi,pOb)-15; if ((t>pOb->yi)&&(t<pOb->y.i+20)) { pOb->Jump=0; pOb->y.i+=15; Turn_Around(pOb); pOb->SeqFile=Sprites[SpriteMap[34]]; Object_TriggerSeq(Arac_JumpLand,pOb); } } else { if (pOb->Frame==16) pOb->Jump=1; if (pOb->AnimStat==AnimDone) { pOb->t1=0; pOb->Mode=&Pattern_Arac; } } Command_Arac(pOb); } 

令人不快的景象。 这种代码风格来自游戏很小的时代,而我是在与68K一起工作时开发出来的。

图片

Source: https://habr.com/ru/post/zh-CN459622/


All Articles