架构和编程Fairchild Channel F

“ F通道的自制程序就像通过硬件跳线编程精灵...”
/ chadtower,ariariage论坛/



Fairchild Channel F游戏机,也称为VES,于1976年11月问世。 与以前的乒乓球,网球(在同一行中,前苏联称为“视频体育”)不同,它具有非常重要的区别-微处理器和带有程序的盒带。 在此之前,游戏机中的游戏是按照严格的逻辑实现的-在现代意义上,该程序是不存在的。

Fairchild Channel F发行至1983年。 在这段时间内,这些游戏机的销量超过了百万分之一, 发行了大约30-40 款游戏 ,其中有些已经在2000年代了。

说到使用微处理器的优越性,值得注意的是,我在上一篇文章中谈到的RCA Studio II仅晚了几个月,但事实证明它比Channel F弱得多,这就是为什么它销售失败。 然而,不到一年后,Atari VCS出现了,并从市场上取代了Channel F.。

这样,Fairchild_Channel_F的开发就没有了。 在System II和几个克隆版本中,例如Saba Videoplay 2(1979),区别主要在于机身,操纵杆(顺便说一下,除了通常的位置,旋钮的旋转之外,他们都知道)和筹码数量。 在架构上,一切都几乎相同。

什么是F频道?

中央处理器


该处理器在那个时代的传统中,是由同一家Fairchild公司生产的,与游戏机本身相同,被称为F8 en.wikipedia.org/wiki/Fairchild_F8 。 这是1974年的8位处理器,工作频率为1.8 MHz(一条指令占用1到6个时钟周期)。



但是,它只能称为扩展微处理器,因为该处理器由两块芯片组成-包含ALU的3850CPU计算设备,电池,64字节SRAM,执行指令所需的逻辑,两个端口(没有地址总线!)和3851PSU(可编程)存储单元),其中包含1kb的ROM(用于BIOS),指令指针,存储器寻址方案,中断,计时器(通道F中未专门使用中断和计时器)。

后来出现了F3859芯片,该芯片将CPU和PSU集成在同一芯片上,并在1990年代发布了Mostek 3870(稍有改进的版本)。 但是,这是另一个故事。 有趣的是,有时F8被称为微控制器(特别是由于存在计时器和端口),并且被称为Intel MCS-48家族(8048)的祖先。

除F通道外,F8处理器还用于VideoBrain计算机和CompuChess国际象棋计算机中。 通常,令人惊讶的是,关于该处理器的信息很少。 除了Fairchild的一些说明以及一些专门针对Channel F的游戏的源代码和示例外,仅此而已。 似乎该处理器尚未在其他任何地方使用,这似乎令人难以置信(鉴于其高级版本已经发布了相当长的时间)。 我将假定所有其他用于军事目的的设备。

现在介绍一下处理器的功能。 反思其寄存器的设置和功能。 我认为这是当时存在的最混乱的体系结构之一(现代的体系结构可能会扩展,但是这种比较是不正确的,因为它们是为编译器设计的。正在使用F8的人们在工作)。

处理器中有很多寄存器。 除了8位电池A和标志寄存器W(I,O,Z,C,S)之外,还有一个“便签本”-64个具有各种功能的8位单元。

前九个单元在诸如“ lr a,7”之类的命令中用作通用寄存器R0-R8(将寄存器R7的内容加载到电池中)。请注意,未显示字母R-仅写入了寄存器编号。确切的含义是,编号或例如,对于lr指令,根本就不可能有数字,例如,如果“ li 7”(将常数加载到电池中),则它就是数字,而不是寄存器。

单元9、10-11(H),12-13(K),14-15(Q)旨在在不同情况下保存其他寄存器,例如调用子程序。

只能通过特殊的ISAR索引寄存器(间接Scratchpad地址寄存器)访问寄存器R16-R63,这是由单元格16-23、24-31、32-39、40-47、48-55、56-63形成的六个八字节缓冲区。

六位ISAR被分为3位的两个部分。 当将ISAR增加或减少1时,仅影响低3位-即 寻址是在上述六个八个字节的缓冲区之一中进行的(同时,可以通过特殊的br7条件分支指令来跟踪缓冲区的末尾)。

clr ; 0 -> A ; set ISAR to full address Ox27 (octal 27) lisu 2 ; buffer N2 lisl 7 ; index within buffer N2 loop: lr d,a ; A-> buffer N2[index], than decrement ISAR (27, 26, 25, ... ) br7 loop ; go further if low part of ISAR contains 7 (end of buffer N2). if not, go loop again 

在这种情况下,指令“ lr d,a”中的“ d”不是寄存器的名称,而是需要减少ISAR的标志(“ i”-增加,“ s”-保持不变)。

间接寻址的另一种方式是通过DC0寄存器(数据计数器):

  dci data_addr ; data_addr -> DC0 lm ; [data_addr] -> A, DC0 + 1 -> DC0 ... data_addr: db 0,1,2,3,... 

如果需要将数据从一个存储区传输到另一个存储区,则还可以使用xdc命令,该命令交换寄存器DC0和DC1的内容。 即 我们从DC0指向的地址读取,然后执行xdc并写入DC1现在指向的地址。 然后再次xdc等 即 DC1是一种影子寄存器,用于存储DC0的副本。 无法直接访问它(命令xdc除外)。

上面的例子仅说明了部分可能性,实际上,还有更多的可能性。

同样在F8中,有四个端口-0、1、4、5,您可以使用out命令将其写入并使用in命令来进行读取。 在通道F中,端口用于输出图形,声音和读取操纵杆状态。

我不会再讨论其他指令,例如算术,转换等-它们是相当标准的。 我只注意到,可以在其上执行操作的寄存器的选择非常有限,因此由于需要不断地来回移动值,因此代码迅速增长。

没有减法(只有加法)。 每单位的减量(ds)和增量(inc)指令是不对称的。 ds仅适用于寄存器r0-r8,inc-仅适用于电池。

无条件跳变会损坏电池。

常规循环的示例:

  li 25 ; (r4) number of iterations lr 4,a next: ds 4 ; r4-- bnz next ; until r4 == 0 

例行程序


由于F8没有硬件堆栈,因此嵌套子程序调用会遇到困难。 正常的调用和返回如下所示:

  ; ...code pi sub ; Pushes address of next instruction to PC1 ; address of sub is stored in PC0 (jump to subroutine) ; ...code continues sub: ; ... often used code pop ; Move return address from PC1 to PC0 

PC0是常规指令指针。 PC1-所谓的“堆栈寄存器”。 它与堆栈无关,仅在调用子例程时将PC0保存在堆栈中。

如果从sub调用另一个子例程,则返回地址将被覆盖并且需要复杂(将第一个返回地址保存在寄存器K中):

  prog: ; ...do something... pi sub1 ; Address of next instruction stored in PC1 ; sub1 is stored in PC0 (jump to subroutine) ; ...do more... sub1: lr k,p ; Copy PC1 to K, original jump address to K ; ...do something... pi sub2 ; Pushes address of next instruction to PC1 ; sub1 is stored in PC0 (jump to subroutine) ; ...do more... pk ; Store address of next instruction in PC1 ; Copy value in K to PC0 (jump back to main) sub2: ; ...do something... pop ; Move return address from PC1 to PC0 

如果您还需要第三层嵌套,那么一切都会变得很难过(为此,在BIOS中甚至有两个特殊的例程-pushk和popk)。

一般建议是尝试用宏替换子例程调用。 当然,如果对代码的大小没有严格的限制。

F8中没有硬件堆栈。 如有必要,可以通过ISAR和缓冲区以编程方式实现。

写入RAM并不是很相关(因为缺少一个),但是看起来像这样:

  li $FF ; set value dci $3800 ; set target address st ; write 

记忆


尽管这听起来有些奇怪,但是仙童频道F中没有RAM。 现有的2 KB视频内存(MK4027)不会显示在地址空间中,并且实际上是不可读的,它们是通过端口写入的。 微处理器的寄存器,即使多达64个,也几乎不认为是RAM正确的。

可执行程序存储在可移动ROM盒式磁带中,通常容量为2kb(某些现代游戏使用3k,4k和5k盒式磁带)。 此外,还有一个内置的处理器芯片1KB ROM ROM,其中包含一个简单的游戏,例如网球,几个有用的例程和几个字符的图像。

在地址空间中,BIOS的位置从$ 0000到$ 07ff,盒式ROM从$ 0800开始。

图形


通道F的图形功能非常原始,因为那里根本就没有单独芯片形式的视频控制器-一切都以常规逻辑实现,例如移位寄存器,门和运算放大器。 不同的来源提到不同的分辨率是很不寻常的,并且有很多选择。 事实是,可用的2 KB视频内存意味着128 x 64的分辨率,但实际上这远非如此。 首先,很大程度上取决于在此特定电视上形成的图像的哪个区域可见(因为前4列根本没有正式使用)。 其次,在面板下方使用最后几列。 第三,部分存储器根本不使用。

结果,实际分辨率可以大致估计为具有8种颜色的95 x 58像素(但是,其分辨率比RCA Studio II的黑白64x32好得多)。

大多数控制台以NTSC版本发布,但也存在PAL。 正如他们所说(行数相同),没有实际差异。

本质上,这种简单的熨斗仅允许您在屏幕上绘制点。 尽管显示的颜色总数为8,但是一行中只能显示4种颜色(您可以随意将其称为调色板)。 调色板是为每行单独设置的,并且存储在一个相当奇怪的地方-每行的列125和126(无论如何在可见区域之外)。 分别通过在这两列中绘制像素来更改调色板。


(屏幕上实际可见的视频存储区域和设置调色板的区域以黄色突出显示)

如上所述,只有一种方法可以通过端口将数据写入VRAM。 这表示颜色,列,行:

X写入端口4,Y写入端口5,颜色写入端口1,之后通过将常量写入端口0来传输数据:

  ; set color (2 bit per pixel) li $00 ; color ($00 = green, $40 = red, $80 = blue, $C0 = background) outs 1 li 104 ; X com outs 4 ; set the row li 61 ; Y com outs 5 ; transfer data to VRAM li $60 outs 0 li $50 outs 0 ; wait for update lis 6 delay: ai $ff bnz delay 

需要延迟才能记录所有内容,否则可能无法画出下一点。 在正式版中,列和行中仍添加了4(为简化起见,省略了)

因此,用点(循环)填充整个屏幕大约需要一秒钟。 重要的是要注意,除了屏幕更新非常慢之外,还存在这样的事实,即没有办法等待光束返回通过框架。 因此,即使是小的重画也不可避免地伴随有闪烁。

现在介绍调色板。 严格来说,每行都有两种模式-黑色和白色(无论绘制的是什么像素,背景都是黑色,前景只有白色)。

在前景色模式下,总是有三个-红色,绿色,蓝色(rgb)。 加上三种背景颜色之一-灰色,浅蓝色,浅绿色。

要在第125和126列中设置调色板,请输入以下值:

 x=125 x=126 palette --------------------------------------------------------------------- 00 00 COLOR: rgb, light green bg 00 ff COLOR: rgb, light blue bg ff 00 COLOR: rgb, gray bg ff ff B/W: www, black bg 

在典型的游戏中,他们通常这样做:首先,他们设置一定的一般背景,为此您可以使用现成的BIOS过程:
  li $c6 ; $21 - b/w palette, fill with black. $c6 - color palette, fill with gray lr 3, A pi clrscrn ; clrscrn BIOS call 

然后,如有必要,用黑白调色板划出一条带(例如,在黑色背景上显示带有白色数字的游戏分数)


然后,他们将像素设置为三种颜色之一(如果背景分别为灰色,则分别为r,g,b)。 结果,当然有8种颜色,但是在特定位置放置任意颜色的点非常容易-这是不可能的。 这是一组图片 ,提供了一些颜色及其组合的概念。

实际上,就此而言,所有这些图形最终都将结束-您想要做的所有事情都是通过手动绘制像素来完成的。 通过有用的例程,BIOS具有字符输出。 但是,出于节省空间的原因,ROM中仅包含数字和单个字符的图像,大小为5x8像素:


但是,撤回它们的过程很有用,可以按以下方式使用:

  li 25 ; column lr 1,a li 25 ; row lr 2,a li %11000000 ; eg $c0 - green "0" lr 0,a ; a -> r0 pi drawchar ; call subroutine 

在上述版本中,寄存器r0中的高两位数字确定颜色(10-红色,11-绿色,01-蓝色,00-透明),其余-字符的序列号(0 1 2 3 4 5 6 7 8 9 G?T SPACE MX块:-中心||左||`),从零开始。 寄存器r1和r2分别放置在列和行中。

一个更实际的选择是不考虑位:

  li 20 ; x lr 1,a ; a -> r1 li 10 ; y lr 2,a ; a -> r2 li $40 ; char color in bits 6,7: $80 (%10000000) - red, $c0 (%11000000) - green, $40 (%01000000) - blue, $00 (%00000000) - transparent oi 1 ; index of char ( eg 3 for "3" ) lr 0,a ; combined color + char index -> r0 pi drawchar ; call subroutine 

为了了解该平台,我为Chaos Constructions'2019的小型介绍比赛编写了256字节的介绍 。 没什么特别的,但是请注意为什么在那里使用逐行调色板更改。 沿水平方向爬行的条纹会突出显示其下方的线条,用黑色临时替换整个背景,用白色替换所有像素。 由于您不需要覆盖像素本身(并且以后也不需要还原它们),因此可以非常快速且无闪烁地制作这样的“背光”。

第二点是字母“ CC”。 由于字母“ C”不在BIOS中,因此字母GG与数字1的重叠用于获得反“ CC”。



声音


声音不好。 正式地,有三种声音-120Hz,500 Hz和1 KHz。 实际上,要获得除咔嗒声和嘎吱嘎吱声以外的其他东西是有问题的。 此外,他们说在PAL和NTSC机器之间以及旧版本和新版本之间,声音也有所不同。 但是,对于典型的游戏-足够了。 通过端口打开和关闭声音:

  li %01000000 ; 1khz beep $40 outs 5 li %10000000 ; 500hz beep $80 outs 5 li %11000000 ; 120hz beep $c0 outs 5 ; some pause clr outs 5 ; turn off sound 

人们甚至玩音乐都很开心。 最好的 样本在远程上类似于PC扬声器。 确实,无论如何都没有实际意义-所有处理器资源都用于音乐,没有什么特别的事情可以做。

开发工具


当前,有现成的必要软件选择,称为“ Development Pack”。

这包括DASM汇编程序,反汇编程序,MESS仿真器(带有调试器)。 所有这些都至少在Windows 7下可以正常工作。


组装和启动参数:

 dasm.exe test.asm -f3 -otest.bin messd channelf -cartridge %cartPath%\test.bin -w -effect sharp -r 640x480 -ka 

该模拟器非常好,尽管那里的调试器非常奇怪。 我无法立即配置新版本的MAME / MESS(我注意到,每次为据说不支持的不受欢迎的平台设置MAME都是不平凡的任务)。

仿真器假定可见区域的分辨率对应于minx = 5,minY = 5,maxX = 105,maxY = 61

由于没有在没有实时测试结果的情况下在模拟器下编写某些东西的乐趣,因此我不得不解决ROM模拟器的问题。 应我的要求, tnt23制造了一个特殊的盒式磁带(亚历山大· 诺沃基洛夫 (Alexander Novozhilov)打印了一个盒子),其中插入了EEPROM 28C16A。 由于F8寻址的特殊性,我仍然不得不在eBay上购买一个古老的Fairchild 3853芯片,结果,通过对EEPROM编程,可以看到代码在带电机器上的外观。


此外,tnt23附加了Channel F S-Video输出(通常只能通过天线输入连接到电视),从而大大改善了图像质量和色彩再现。

有关Fairchild Channel F的故事:



资源资源


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


All Articles