[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:14.49,0:00:17.81,Default,,0000,0000,0000,,下一个演讲 我个人十分期待 Dialogue: 0,0:00:17.83,0:00:23.19,Default,,0000,0000,0000,,我也知道你们很多人为此在这里等候 Dialogue: 0,0:00:24.26,0:00:26.21,Default,,0000,0000,0000,,我也非常激动 Dialogue: 0,0:00:26.86,0:00:31.59,Default,,0000,0000,0000,,我自己有台GameBoy 我也很荣幸能拥有一台 Dialogue: 0,0:00:31.59,0:00:36.48,Default,,0000,0000,0000,,我一直放着 有时也拿出来玩玩 Dialogue: 0,0:00:36.49,0:00:39.04,Default,,0000,0000,0000,,当然一般情况下还是玩模拟器多 Dialogue: 0,0:00:39.77,0:00:43.86,Default,,0000,0000,0000,,而且我只在模拟器上玩我拥有实体卡带的游戏 Dialogue: 0,0:00:45.82,0:00:52.53,Default,,0000,0000,0000,,本来就应该是这样的 对吧 Dialogue: 0,0:00:54.05,0:00:54.46,Default,,0000,0000,0000,,嗯是的 Dialogue: 0,0:00:55.77,0:00:57.25,Default,,0000,0000,0000,,非常期待 Dialogue: 0,0:00:57.68,0:01:01.52,Default,,0000,0000,0000,,顺便 我个人在Gameboy平台上最喜欢的游戏 Dialogue: 0,0:01:02.26,0:01:07.04,Default,,0000,0000,0000,,第一个 是Megaman 2 Dialogue: 0,0:01:07.66,0:01:14.10,Default,,0000,0000,0000,,随后是Wario Land, Mystic Quest 如果你不同意的话 Dialogue: 0,0:01:14.10,0:01:16.56,Default,,0000,0000,0000,,那说明你还不够了解我 Dialogue: 0,0:01:18.68,0:01:24.64,Default,,0000,0000,0000,,好了讲讲演讲吧 Dialogue: 0,0:01:24.94,0:01:26.56,Default,,0000,0000,0000,,非常期待 Dialogue: 0,0:01:27.31,0:01:31.78,Default,,0000,0000,0000,,主讲是Michael Steil Dialogue: 0,0:01:32.64,0:01:36.43,Default,,0000,0000,0000,,他在25C3给过一个非常棒的演讲 Dialogue: 0,0:01:36.67,0:01:40.52,Default,,0000,0000,0000,,“The Ultimate Commodore 64 Talk” 现在 Dialogue: 0,0:01:40.71,0:01:43.70,Default,,0000,0000,0000,,为大家带来的是 “The Ultimate Gameboy Talk” Dialogue: 0,0:01:43.88,0:01:44.93,Default,,0000,0000,0000,,很期待 Dialogue: 0,0:01:45.15,0:01:48.98,Default,,0000,0000,0000,,Michael Steil 白天他在工作研究操作系统相关技术 Dialogue: 0,0:01:49.17,0:01:51.73,Default,,0000,0000,0000,,晚上回到家就研究这些古董系统 Dialogue: 0,0:01:51.92,0:01:55.15,Default,,0000,0000,0000,,在之前 它是个游戏机破解工作者 Dialogue: 0,0:01:55.15,0:01:57.75,Default,,0000,0000,0000,,请为他热烈的鼓掌 Dialogue: 0,0:01:57.87,0:01:59.74,Default,,0000,0000,0000,,把讲台交给Michel Dialogue: 0,0:02:07.64,0:02:09.19,Default,,0000,0000,0000,,大家好 Dialogue: 0,0:02:09.100,0:02:11.42,Default,,0000,0000,0000,,那 我的名字是Michael Steil Dialogue: 0,0:02:11.54,0:02:13.48,Default,,0000,0000,0000,,这次讲座是“The Ultimate Gameboy Talk” (一场讲座,关于Gameboy的一切) Dialogue: 0,0:02:21.98,0:02:23.81,Default,,0000,0000,0000,,这场讲座的主要想法就是 Dialogue: 0,0:02:23.93,0:02:28.18,Default,,0000,0000,0000,,在60分钟内 尽可能多得谈谈Gameboy的各种硬件细节 Dialogue: 0,0:02:28.36,0:02:31.53,Default,,0000,0000,0000,,60分钟,关于Gameboy的一切 Dialogue: 0,0:02:31.74,0:02:36.06,Default,,0000,0000,0000,,我准备了大约200张幻灯片 800张不同的表 Dialogue: 0,0:02:36.11,0:02:38.69,Default,,0000,0000,0000,,所以信息密度可能比一般稍微高了一点 Dialogue: 0,0:02:38.99,0:02:41.05,Default,,0000,0000,0000,,所以赶紧开始吧 Dialogue: 0,0:02:41.15,0:02:42.76,Default,,0000,0000,0000,,这次的GameBoy演讲 Dialogue: 0,0:02:42.91,0:02:45.77,Default,,0000,0000,0000,,算是一个大系列之一 Dialogue: 0,0:02:45.91,0:02:47.81,Default,,0000,0000,0000,,我在几年前讲了Commodore 64 Dialogue: 0,0:02:48.01,0:02:50.86,Default,,0000,0000,0000,,后来有人就接上讲了Atari 2600 Dialogue: 0,0:02:51.13,0:02:53.80,Default,,0000,0000,0000,,讲了Galaksija 还有Amiga 500 Dialogue: 0,0:02:53.93,0:02:55.09,Default,,0000,0000,0000,,所以现在又轮到我了 Dialogue: 0,0:02:56.85,0:02:58.56,Default,,0000,0000,0000,,我选择了GameBoy Dialogue: 0,0:02:58.70,0:03:00.61,Default,,0000,0000,0000,,为什么GameBoy那么有趣 Dialogue: 0,0:03:00.78,0:03:03.52,Default,,0000,0000,0000,,因为他们销售了很多很多的GameBoy Dialogue: 0,0:03:03.71,0:03:06.45,Default,,0000,0000,0000,,GameBoy和GBC加起来就有1亿1800万台 Dialogue: 0,0:03:06.61,0:03:11.45,Default,,0000,0000,0000,,如果再考虑上兼容GameBoy的GBA机型 不包括GBM Dialogue: 0,0:03:11.52,0:03:13.91,Default,,0000,0000,0000,,加起来这几乎是2亿台机器 Dialogue: 0,0:03:14.11,0:03:17.84,Default,,0000,0000,0000,,大约有1600款游戏 Dialogue: 0,0:03:19.31,0:03:23.62,Default,,0000,0000,0000,,从1989年开始生产 8-Bit型号一直生产到2003年 Dialogue: 0,0:03:23.74,0:03:26.69,Default,,0000,0000,0000,,一样,如果考虑兼容的GBA型号 Dialogue: 0,0:03:26.84,0:03:31.26,Default,,0000,0000,0000,,8-Bit兼容机一直生产到2009年 Dialogue: 0,0:03:31.33,0:03:32.99,Default,,0000,0000,0000,,也就是20年 相当厉害 Dialogue: 0,0:03:34.36,0:03:36.34,Default,,0000,0000,0000,,我们再来看看当时的竞争对手 Dialogue: 0,0:03:36.48,0:03:38.35,Default,,0000,0000,0000,,就在当时 就在GameBoy发布后 Dialogue: 0,0:03:38.61,0:03:42.67,Default,,0000,0000,0000,,Atari发布了Lynx SEGA发布了Game Gear NEC发布了Turbo Express Dialogue: 0,0:03:42.78,0:03:45.67,Default,,0000,0000,0000,,这些竞品有一个共同点 它们都有彩屏 Dialogue: 0,0:03:45.78,0:03:47.36,Default,,0000,0000,0000,,很棒的彩屏 Dialogue: 0,0:03:47.44,0:03:51.79,Default,,0000,0000,0000,,但是还有一个共同点 就是渣续航 大约3-5小时 Dialogue: 0,0:03:51.94,0:03:54.28,Default,,0000,0000,0000,,然而GameBoy可以做到15-30小时 Dialogue: 0,0:03:54.47,0:03:57.29,Default,,0000,0000,0000,,然而妥协就是,只有一个这样的屏幕 Dialogue: 0,0:03:57.39,0:04:00.44,Default,,0000,0000,0000,,而且一旦开始卷动就很难看清楚东西 Dialogue: 0,0:04:01.67,0:04:04.85,Default,,0000,0000,0000,,当然,并不是所有的GameBoy都是这个情况 Dialogue: 0,0:04:06.20,0:04:09.41,Default,,0000,0000,0000,,最初的GameBoy 也是生产最长时间的型号 Dialogue: 0,0:04:09.55,0:04:14.09,Default,,0000,0000,0000,,最初代号是DMG 代表的是Dot-Matrix Game(点阵游戏) Dialogue: 0,0:04:14.39,0:04:20.51,Default,,0000,0000,0000,,1996年他们发布了GBP 带有效果好得多的屏幕 体积也小了很多 代号MGB Dialogue: 0,0:04:20.64,0:04:23.64,Default,,0000,0000,0000,,GBL只在日本发售 带有屏幕背光 Dialogue: 0,0:04:23.75,0:04:29.46,Default,,0000,0000,0000,,最后是GBC 2倍的CPU速度 2倍的内存 2倍的显存 以及支持彩色 Dialogue: 0,0:04:31.49,0:04:36.41,Default,,0000,0000,0000,,接着是GBA系列 架构完全不同 基于ARM CPU Dialogue: 0,0:04:36.41,0:04:40.80,Default,,0000,0000,0000,,但是仍然和GB、GBC游戏100%兼容 Dialogue: 0,0:04:40.95,0:04:45.04,Default,,0000,0000,0000,,至于GBA SP,存在两种型号 Dialogue: 0,0:04:45.19,0:04:48.53,Default,,0000,0000,0000,,如果你要买的话,记得买AGS101 Dialogue: 0,0:04:48.61,0:04:51.01,Default,,0000,0000,0000,,也就是带有背光而不是前光的型号 Dialogue: 0,0:04:52.08,0:04:55.16,Default,,0000,0000,0000,,而且可以看见任天堂总是有一点超前 Dialogue: 0,0:04:55.16,0:04:59.42,Default,,0000,0000,0000,,不单单是做了翻盖设计 而且还需要一个转接头才能接一般的耳机 Dialogue: 0,0:05:06.07,0:05:09.40,Default,,0000,0000,0000,,如果你想在电视上玩GameBoy Dialogue: 0,0:05:09.55,0:05:13.74,Default,,0000,0000,0000,,有两种选择 要么是Super Nintendo插上Super Game Boy Dialogue: 0,0:05:13.84,0:05:19.100,Default,,0000,0000,0000,,有两个版本 SGB2是日本专有型号 有专门的计时系统 不会比正常的快3% Dialogue: 0,0:05:20.12,0:05:23.95,Default,,0000,0000,0000,,以及Game Boy Player 搭配NGC使用 Dialogue: 0,0:05:24.01,0:05:27.14,Default,,0000,0000,0000,,这三个都是内置了完整的GameBoy硬件 Dialogue: 0,0:05:27.26,0:05:31.13,Default,,0000,0000,0000,,基本就是一个GameBoy 只是把图形输出到主机而不是自己的屏幕 Dialogue: 0,0:05:32.44,0:05:34.13,Default,,0000,0000,0000,,所以GameBoy具体的外观 Dialogue: 0,0:05:34.27,0:05:38.78,Default,,0000,0000,0000,,一个2.6英寸的屏幕 按键 单声道喇叭 耳机是立体的 Dialogue: 0,0:05:38.99,0:05:42.27,Default,,0000,0000,0000,,有一个联机口 通过串行总线连接两台GameBoy Dialogue: 0,0:05:42.38,0:05:43.75,Default,,0000,0000,0000,,对比度和音量调节旋钮 Dialogue: 0,0:05:43.93,0:05:46.90,Default,,0000,0000,0000,,背面 这里是插游戏卡带的地方 Dialogue: 0,0:05:47.06,0:05:48.79,Default,,0000,0000,0000,,这里则是安装电池的地方 Dialogue: 0,0:05:49.23,0:05:51.32,Default,,0000,0000,0000,,一般的游戏卡带就长这个样子 Dialogue: 0,0:05:51.46,0:05:53.15,Default,,0000,0000,0000,,一般的游戏卡带里面一般也就是一片ROM芯片 Dialogue: 0,0:05:53.15,0:05:54.48,Default,,0000,0000,0000,,没有什么特殊的 (具体后面会讲) Dialogue: 0,0:05:55.59,0:05:57.12,Default,,0000,0000,0000,,参数 Dialogue: 0,0:05:57.28,0:05:58.90,Default,,0000,0000,0000,,GameBoy的参数是怎么样的 Dialogue: 0,0:05:58.97,0:06:02.26,Default,,0000,0000,0000,,拿来和一些其它可能根本不具备可比性的机型比一比吧 Dialogue: 0,0:06:02.35,0:06:04.68,Default,,0000,0000,0000,,CPU是1MHz的8Bit处理器 Dialogue: 0,0:06:04.68,0:06:10.32,Default,,0000,0000,0000,,有人可能会讲这里错了 应该是个4MHz的CPU 但是我一会会解释为什么这里称之为1MHz Dialogue: 0,0:06:11.74,0:06:15.16,Default,,0000,0000,0000,,8KB的内存 对于这类的游戏机其实算是充裕了 Dialogue: 0,0:06:15.30,0:06:17.40,Default,,0000,0000,0000,,显存(VRAM)也是8KB 稍微有点紧张 Dialogue: 0,0:06:17.58,0:06:24.41,Default,,0000,0000,0000,,分辨率160*144 非常糟糕 但是对于这个屏幕尺寸 其实效果也还可以 Dialogue: 0,0:06:24.62,0:06:29.25,Default,,0000,0000,0000,,同屏最大4种颜色 就是4级灰度 Dialogue: 0,0:06:29.42,0:06:32.18,Default,,0000,0000,0000,,每行最多10个精灵 Dialogue: 0,0:06:32.37,0:06:35.60,Default,,0000,0000,0000,,所以如果和这里其它的一些系统比较的话 Dialogue: 0,0:06:35.80,0:06:43.41,Default,,0000,0000,0000,,很明显 GameBoy比Atari2600要先进得多 但是却又比不上SNES Dialogue: 0,0:06:43.56,0:06:48.34,Default,,0000,0000,0000,,更接近于一般的NES(美版红白机)或者是Commodore 64 Dialogue: 0,0:06:48.53,0:06:53.67,Default,,0000,0000,0000,,有趣的是 NES和C64是在80年代早期发布的 Dialogue: 0,0:06:53.87,0:06:55.31,Default,,0000,0000,0000,,GameBoy是89年 Dialogue: 0,0:06:55.50,0:07:01.01,Default,,0000,0000,0000,,而且如我前面所说 兼容机一直生产到了2009年 Dialogue: 0,0:07:01.16,0:07:02.94,Default,,0000,0000,0000,,这也就非常有趣了 Dialogue: 0,0:07:03.07,0:07:08.97,Default,,0000,0000,0000,,它是8-Bit机 但是是最晚一批大量使用的8-Bit游戏机 Dialogue: 0,0:07:10.76,0:07:12.02,Default,,0000,0000,0000,,看看内部 Dialogue: 0,0:07:12.16,0:07:14.95,Default,,0000,0000,0000,,右边的板没什么花头 Dialogue: 0,0:07:15.05,0:07:19.08,Default,,0000,0000,0000,,从正面看 LCD就是连接在这块板上 以及扬声器和按键 Dialogue: 0,0:07:20.79,0:07:23.46,Default,,0000,0000,0000,,背后这块板就有趣多了 Dialogue: 0,0:07:23.64,0:07:27.91,Default,,0000,0000,0000,,可以看见3块芯片 这个是DMG 也就是最初的型号 Dialogue: 0,0:07:28.08,0:07:29.87,Default,,0000,0000,0000,,2片一样的RAM芯片 Dialogue: 0,0:07:29.87,0:07:32.55,Default,,0000,0000,0000,,一片工作内存(WRAM) 一片视频内存(VRAM) Dialogue: 0,0:07:32.75,0:07:35.96,Default,,0000,0000,0000,,中间这个叫DMG-CPU Dialogue: 0,0:07:36.12,0:07:38.74,Default,,0000,0000,0000,,然而其实更应该被称为SoC(System on a Chip) Dialogue: 0,0:07:38.96,0:07:44.82,Default,,0000,0000,0000,,正常这类的系统都应该有很多芯片 Dialogue: 0,0:07:44.82,0:07:48.33,Default,,0000,0000,0000,,但是这里全部都集成进了一个芯片 也就这个DMG芯片 Dialogue: 0,0:07:48.47,0:07:51.78,Default,,0000,0000,0000,,来对比一下其它的GameBoy机型 Dialogue: 0,0:07:51.78,0:07:54.24,Default,,0000,0000,0000,,比如SGB 这些芯片看起来很接近 Dialogue: 0,0:07:54.24,0:07:57.07,Default,,0000,0000,0000,,其实基本上就是一样的 Dialogue: 0,0:07:58.28,0:08:05.20,Default,,0000,0000,0000,,GBP 稍微优化了一下 只带有一片RAM芯片 Dialogue: 0,0:08:05.28,0:08:11.06,Default,,0000,0000,0000,,GBL看起来基本没有区别 只是MGB系列的另外一个小型号 Dialogue: 0,0:08:11.06,0:08:12.45,Default,,0000,0000,0000,,带有背光而已 Dialogue: 0,0:08:12.62,0:08:15.79,Default,,0000,0000,0000,,接着是SGB2 基于GBP设计 Dialogue: 0,0:08:17.11,0:08:19.48,Default,,0000,0000,0000,,这是GBC内部的样子 Dialogue: 0,0:08:19.65,0:08:21.33,Default,,0000,0000,0000,,都有一个巨大的集成片 Dialogue: 0,0:08:22.47,0:08:24.51,Default,,0000,0000,0000,,这个呢 这个比较特殊 Dialogue: 0,0:08:24.67,0:08:26.84,Default,,0000,0000,0000,,可能从标识上不容易认 Dialogue: 0,0:08:27.02,0:08:28.80,Default,,0000,0000,0000,,这个是GB Boy Dialogue: 0,0:08:29.02,0:08:31.89,Default,,0000,0000,0000,,总是有公司山寨GameBoy Dialogue: 0,0:08:32.06,0:08:35.39,Default,,0000,0000,0000,,这个型号 是一个相当完美的克隆 Dialogue: 0,0:08:35.50,0:08:41.14,Default,,0000,0000,0000,,基本上就是 完全抄了一个原版的芯片 Dialogue: 0,0:08:42.42,0:08:44.95,Default,,0000,0000,0000,,来自中国的山寨GameBoy Dialogue: 0,0:08:45.06,0:08:48.30,Default,,0000,0000,0000,,而且至今都可以在eBay上花三四十刀买到 Dialogue: 0,0:08:49.08,0:08:53.14,Default,,0000,0000,0000,,然而很遗憾晶振快了30% 游戏都玩不了了 Dialogue: 0,0:08:56.19,0:08:58.41,Default,,0000,0000,0000,,回来讲DMG的板子 Dialogue: 0,0:08:58.41,0:09:00.84,Default,,0000,0000,0000,,DMG CPU还是相当有趣的 Dialogue: 0,0:09:00.86,0:09:02.39,Default,,0000,0000,0000,,他接管整个系统的一切 Dialogue: 0,0:09:02.70,0:09:04.63,Default,,0000,0000,0000,,DMG CPU包括了什么 Dialogue: 0,0:09:04.82,0:09:09.70,Default,,0000,0000,0000,,CPU 中断控制器 定时器 内存 启动ROM Dialogue: 0,0:09:10.06,0:09:16.11,Default,,0000,0000,0000,,还有所有的外设以及IO控制器 摇杆 用于联机的串行控制器 Dialogue: 0,0:09:16.11,0:09:17.79,Default,,0000,0000,0000,,声音控制器 还有 图形控制器 Dialogue: 0,0:09:17.79,0:09:19.26,Default,,0000,0000,0000,,也就是PPU (Pixel Processing Unit) Dialogue: 0,0:09:19.95,0:09:21.43,Default,,0000,0000,0000,,来讲讲CPU吧 Dialogue: 0,0:09:21.67,0:09:22.86,Default,,0000,0000,0000,,历史角度来讲 Dialogue: 0,0:09:23.09,0:09:24.76,Default,,0000,0000,0000,,最初的GameBoy,1989年 Dialogue: 0,0:09:24.96,0:09:29.93,Default,,0000,0000,0000,,发布时间是在NES的和SNES的之间 Dialogue: 0,0:09:31.23,0:09:33.04,Default,,0000,0000,0000,,NES搭载的是6502处理器 Dialogue: 0,0:09:33.24,0:09:36.41,Default,,0000,0000,0000,,SNES搭载的是65816处理器 Dialogue: 0,0:09:36.41,0:09:38.39,Default,,0000,0000,0000,,也就是相同CPU的16位版本 Dialogue: 0,0:09:39.14,0:09:42.82,Default,,0000,0000,0000,,所以显然GameBoy搭载了SHARP LR35902 (强行显然2333) Dialogue: 0,0:09:44.13,0:09:47.59,Default,,0000,0000,0000,,SHARP LR35902是什么 Dialogue: 0,0:09:48.17,0:09:49.35,Default,,0000,0000,0000,,这个和6502没啥关系 Dialogue: 0,0:09:49.57,0:09:53.76,Default,,0000,0000,0000,,更接近于i8080和Z80 Dialogue: 0,0:09:53.76,0:09:54.40,Default,,0000,0000,0000,,但是也不是其中任何一种 Dialogue: 0,0:09:55.25,0:09:56.96,Default,,0000,0000,0000,,两种cpu都相当有趣 Dialogue: 0,0:09:57.17,0:09:59.98,Default,,0000,0000,0000,,比如8080用于Altair Dialogue: 0,0:10:00.21,0:10:03.41,Default,,0000,0000,0000,,也就是Bill Gates最初写程序并销售的平台 Dialogue: 0,0:10:03.63,0:10:09.99,Default,,0000,0000,0000,,Z80则是用于所有没有采用6502的8bit家用机 Dialogue: 0,0:10:10.18,0:10:11.48,Default,,0000,0000,0000,,相当成功的架构 Dialogue: 0,0:10:12.69,0:10:16.44,Default,,0000,0000,0000,,所以如果你想象 这是i8080的功能 Dialogue: 0,0:10:16.63,0:10:18.83,Default,,0000,0000,0000,,这是Z80的功能 Dialogue: 0,0:10:18.83,0:10:21.48,Default,,0000,0000,0000,,也就是一个超集 而且完全向下兼容 Dialogue: 0,0:10:24.01,0:10:28.01,Default,,0000,0000,0000,,然后这个 是GameBoy CPU Dialogue: 0,0:10:30.11,0:10:33.89,Default,,0000,0000,0000,,核心架构是相同的 也就8080的那些 Dialogue: 0,0:10:34.10,0:10:39.30,Default,,0000,0000,0000,,比如寄存器组 指令编码 这些都是一样的 Dialogue: 0,0:10:39.94,0:10:41.50,Default,,0000,0000,0000,,当然也有一些不支持的功能 Dialogue: 0,0:10:42.18,0:10:44.64,Default,,0000,0000,0000,,但是又支持一部分Z80的功能 Dialogue: 0,0:10:44.83,0:10:47.21,Default,,0000,0000,0000,,然而大部分的Z80功能都不支持 Dialogue: 0,0:10:47.43,0:10:49.40,Default,,0000,0000,0000,,接着又在这之上加了一点自己的功能 Dialogue: 0,0:10:50.46,0:10:51.66,Default,,0000,0000,0000,,来看一遍吧 Dialogue: 0,0:10:51.93,0:10:55.58,Default,,0000,0000,0000,,先来讲讲8080的架构 Dialogue: 0,0:10:55.83,0:10:57.54,Default,,0000,0000,0000,,它拥有这些寄存器 Dialogue: 0,0:10:57.54,0:11:02.67,Default,,0000,0000,0000,,一个累加器 可以用于进行算数运算 其它寄存器不行 Dialogue: 0,0:11:02.81,0:11:04.05,Default,,0000,0000,0000,,一个状态寄存器 Dialogue: 0,0:11:04.10,0:11:08.52,Default,,0000,0000,0000,,在GB内 只有两个有用的标志位 零 和 进位 Dialogue: 0,0:11:08.72,0:11:11.01,Default,,0000,0000,0000,,剩下两个是用于十进制调整的 Dialogue: 0,0:11:11.19,0:11:14.57,Default,,0000,0000,0000,,然后是BCDEHL 6个8位寄存器 Dialogue: 0,0:11:14.80,0:11:19.04,Default,,0000,0000,0000,,但是你可以把B和C合起来 变成BC Dialogue: 0,0:11:19.24,0:11:21.01,Default,,0000,0000,0000,,DE HL同理 Dialogue: 0,0:11:21.15,0:11:25.38,Default,,0000,0000,0000,,所以你实际上拥有可以作为指针的16位寄存器 Dialogue: 0,0:11:25.93,0:11:30.13,Default,,0000,0000,0000,,所以加起来一共有4个16位计算器 Dialogue: 0,0:11:30.81,0:11:34.53,Default,,0000,0000,0000,,7个8位寄存器 加上一个特殊的指针寄存器 Dialogue: 0,0:11:34.53,0:11:40.92,Default,,0000,0000,0000,,指向hl寄存器指向的内存地址的数据 Dialogue: 0,0:11:41.19,0:11:45.21,Default,,0000,0000,0000,,可以放到任何可以操作寄存器的指令中使用 Dialogue: 0,0:11:47.54,0:11:49.07,Default,,0000,0000,0000,,然后来看指令 Dialogue: 0,0:11:49.34,0:11:55.48,Default,,0000,0000,0000,,读取/存储指令 同一个指令可以直接或者间接寻址 Dialogue: 0,0:11:55.71,0:11:59.68,Default,,0000,0000,0000,,堆栈是16位的 只能操作16位寄存器 Dialogue: 0,0:11:59.94,0:12:02.54,Default,,0000,0000,0000,,这些是算数和逻辑指令 Dialogue: 0,0:12:02.72,0:12:04.81,Default,,0000,0000,0000,,如之前所说 这些指令只能配合累加器使用 Dialogue: 0,0:12:04.81,0:12:07.62,Default,,0000,0000,0000,,inc和dec(自加自减)指令是例外 可以配合任何寄存器使用 Dialogue: 0,0:12:07.79,0:12:10.89,Default,,0000,0000,0000,,而且也可以配合16位寄存器使用 Dialogue: 0,0:12:11.12,0:12:17.68,Default,,0000,0000,0000,,移位指令 还有控制指令 跳转 调用 返回 条件 间接操作 等等 Dialogue: 0,0:12:17.85,0:12:23.79,Default,,0000,0000,0000,,还有一些杂类的指令 清除设置进位标志 空指令 停机 停用启用中断 Dialogue: 0,0:12:24.40,0:12:26.73,Default,,0000,0000,0000,,中断模型 Dialogue: 0,0:12:27.63,0:12:31.99,Default,,0000,0000,0000,,大部分当时的机器都有一个中断向量来控制中断 Dialogue: 0,0:12:32.12,0:12:34.91,Default,,0000,0000,0000,,然而这个上面 并不是向量 也不止一个 Dialogue: 0,0:12:35.11,0:12:37.17,Default,,0000,0000,0000,,他并不是跳转到一个中断向量 Dialogue: 0,0:12:37.35,0:12:40.30,Default,,0000,0000,0000,,而是跳转到内存中开始部分一个固定的地址 Dialogue: 0,0:12:40.47,0:12:45.32,Default,,0000,0000,0000,,不同的中断对应不同的地址 比如0x40 0x48这种 Dialogue: 0,0:12:46.16,0:12:48.60,Default,,0000,0000,0000,,还有一些软件中断 Dialogue: 0,0:12:48.78,0:12:51.44,Default,,0000,0000,0000,,你可以使用特殊指令跳转到这些地方 Dialogue: 0,0:12:51.64,0:12:54.74,Default,,0000,0000,0000,,RST 0是一个特殊指令 因为就相当于RESET Dialogue: 0,0:12:55.04,0:12:58.71,Default,,0000,0000,0000,,当你启动8080 CPU 他就从0地址开始执行 Dialogue: 0,0:13:00.36,0:13:03.88,Default,,0000,0000,0000,,来谈谈一些不被支持的8080功能 Dialogue: 0,0:13:04.04,0:13:07.80,Default,,0000,0000,0000,,这个是GB的标志位 这个是8080的标志位 Dialogue: 0,0:13:07.95,0:13:14.60,Default,,0000,0000,0000,,它有两个额外的标志 一个是符号位 还算有点用 一个奇偶校验 就不太有用 Dialogue: 0,0:13:14.73,0:13:16.49,Default,,0000,0000,0000,,所以这些指令都是不支持的 Dialogue: 0,0:13:16.64,0:13:20.78,Default,,0000,0000,0000,,还有一些其它指令 因为种种原因 他们决定不包括这些指令 Dialogue: 0,0:13:20.91,0:13:26.80,Default,,0000,0000,0000,,端口IO 你可能在8086上听说过 有独立的端口空间 Dialogue: 0,0:13:26.80,0:13:29.26,Default,,0000,0000,0000,,在8080上也是支持的 但是GameBoy上不支持 Dialogue: 0,0:13:29.26,0:13:31.49,Default,,0000,0000,0000,,因为GB使用了MMIO(内存映射IO) Dialogue: 0,0:13:32.87,0:13:41.21,Default,,0000,0000,0000,,Z80支持大量额外的移位和位移位 设置位 清楚位指令 Dialogue: 0,0:13:41.23,0:13:42.22,Default,,0000,0000,0000,,这些都是支持的 Dialogue: 0,0:13:42.42,0:13:47.20,Default,,0000,0000,0000,,相对跳转 也就是更优化的跳转指令 Dialogue: 0,0:13:47.43,0:13:49.14,Default,,0000,0000,0000,,从中断返回 Dialogue: 0,0:13:49.14,0:13:50.33,Default,,0000,0000,0000,,这些都是支持的 Dialogue: 0,0:13:50.53,0:13:54.00,Default,,0000,0000,0000,,而不支持的则是一些Z80有趣的功能 Dialogue: 0,0:13:54.24,0:13:59.25,Default,,0000,0000,0000,,比如备份寄存器组 额外的寄存器 还有很多很多功能 Dialogue: 0,0:13:59.25,0:14:03.81,Default,,0000,0000,0000,,还有适合复制内存的自加循环指令 Dialogue: 0,0:14:03.98,0:14:07.69,Default,,0000,0000,0000,,不过他们也有一些自己的指令来代替这些 Dialogue: 0,0:14:07.97,0:14:12.80,Default,,0000,0000,0000,,比如它具有访问预减后加指令 Dialogue: 0,0:14:12.80,0:14:19.58,Default,,0000,0000,0000,,比如你要访问hl指针 可以使用预减指令或者后加指令 Dialogue: 0,0:14:21.01,0:14:22.69,Default,,0000,0000,0000,,还有一个叫做 第0页 (Zero Page) 的概念 Dialogue: 0,0:14:22.85,0:14:25.87,Default,,0000,0000,0000,,这个叫法有点晕 因为并不是真正的第0页 Dialogue: 0,0:14:26.17,0:14:27.79,Default,,0000,0000,0000,,而是在内存的顶部 Dialogue: 0,0:14:27.95,0:14:31.60,Default,,0000,0000,0000,,如果你了解6502就知道 这个是从6502借来的概念 Dialogue: 0,0:14:31.91,0:14:40.23,Default,,0000,0000,0000,,含义只是对于在内存最上端的数据可以优化编码 Dialogue: 0,0:14:40.46,0:14:45.76,Default,,0000,0000,0000,,比如原先这样载入需要3个字节 执行需要4个时钟机器周期 Dialogue: 0,0:14:45.76,0:14:49.29,Default,,0000,0000,0000,,现在可以写成这样 也就是2个字节 执行需要3个机器周期 Dialogue: 0,0:14:49.89,0:14:53.15,Default,,0000,0000,0000,,显然得在最高的位置放一些有用的东西 Dialogue: 0,0:14:53.15,0:14:54.65,Default,,0000,0000,0000,,特别是对计时敏感的东西 Dialogue: 0,0:14:54.88,0:14:56.50,Default,,0000,0000,0000,,还有一些额外的堆栈指令 Dialogue: 0,0:14:56.71,0:15:00.09,Default,,0000,0000,0000,,存储SP的指令 一个用于交换一个字节高低4位的指令 Dialogue: 0,0:15:00.09,0:15:04.91,Default,,0000,0000,0000,,这样8个指令 以及一个额外的电源指令 Dialogue: 0,0:15:05.87,0:15:07.53,Default,,0000,0000,0000,,操作码表看起来是这样的 Dialogue: 0,0:15:07.75,0:15:10.07,Default,,0000,0000,0000,,表明了颜色所以看起来更加直观一点 Dialogue: 0,0:15:12.96,0:15:15.96,Default,,0000,0000,0000,,有几个操作码是无效的 或者说没有被用到 Dialogue: 0,0:15:15.96,0:15:18.14,Default,,0000,0000,0000,,如果执行的话都会造成死机 应该算是个好设计 Dialogue: 0,0:15:19.38,0:15:22.39,Default,,0000,0000,0000,,这个比较特殊 操作码CB Dialogue: 0,0:15:22.60,0:15:25.52,Default,,0000,0000,0000,,是个操作码前缀 以此为前缀又有256个操作码 Dialogue: 0,0:15:25.74,0:15:34.85,Default,,0000,0000,0000,,这也就是从Z80借来的滚动、移位指令 以及自己新增加的指令的空间 Dialogue: 0,0:15:35.26,0:15:38.48,Default,,0000,0000,0000,,再来看另外一个指令 只是作为一个例子 Dialogue: 0,0:15:38.73,0:15:42.86,Default,,0000,0000,0000,,这是从一个固定地址载入到累加器 Dialogue: 0,0:15:42.86,0:15:47.39,Default,,0000,0000,0000,,表示需要3个字节 在4MHz下需要16个时钟 Dialogue: 0,0:15:47.39,0:15:52.78,Default,,0000,0000,0000,,虽然存在争议 就是应该是1MHz还是4MHz (实际4MHz 但是把4个周期当1个看) Dialogue: 0,0:15:52.94,0:15:56.41,Default,,0000,0000,0000,,因为所有的时钟周期数都是可以被4整除的 Dialogue: 0,0:15:57.17,0:16:01.44,Default,,0000,0000,0000,,因为整个系统都是和内存挂钩的 Dialogue: 0,0:16:01.50,0:16:06.27,Default,,0000,0000,0000,,CPU只能以RAM能够提供数据的速度来计算 Dialogue: 0,0:16:07.22,0:16:11.62,Default,,0000,0000,0000,,所以你可以说这是一个1MHz的CPU Dialogue: 0,0:16:11.82,0:16:14.24,Default,,0000,0000,0000,,然后这个指令需要4个周期 Dialogue: 0,0:16:14.42,0:16:15.71,Default,,0000,0000,0000,,这个数字就小得多 Dialogue: 0,0:16:15.88,0:16:18.10,Default,,0000,0000,0000,,而且这个数字也才可以和类似的系统进行比较 Dialogue: 0,0:16:18.30,0:16:24.94,Default,,0000,0000,0000,,比如说和同样拥有1MHz内存速度的6502机器比较 Dialogue: 0,0:16:24.94,0:16:28.07,Default,,0000,0000,0000,,所以说 理论上 CPU确实频率是4MHz Dialogue: 0,0:16:28.33,0:16:30.06,Default,,0000,0000,0000,,RAM速度是1MHz Dialogue: 0,0:16:30.27,0:16:34.07,Default,,0000,0000,0000,,PPU以4MHz的速度绘图 Dialogue: 0,0:16:34.29,0:16:36.72,Default,,0000,0000,0000,,连接到速度为2MHz的VRAM Dialogue: 0,0:16:36.93,0:16:38.58,Default,,0000,0000,0000,,所以这里就稍微有点复杂 Dialogue: 0,0:16:38.79,0:16:40.72,Default,,0000,0000,0000,,但是大部分情况下 Dialogue: 0,0:16:40.89,0:16:45.68,Default,,0000,0000,0000,,大部分的数据可以以1MHz为基准表示 Dialogue: 0,0:16:45.91,0:16:49.64,Default,,0000,0000,0000,,但是要精确的话 并不是1MHz Dialogue: 0,0:16:49.86,0:16:54.04,Default,,0000,0000,0000,,而是1MiHz 1024*1024Hz Dialogue: 0,0:16:54.27,0:16:59.17,Default,,0000,0000,0000,,所以他们没有使用十进制 而是用了二进制 Dialogue: 0,0:16:59.34,0:17:00.41,Default,,0000,0000,0000,,很有趣 Dialogue: 0,0:17:00.62,0:17:05.31,Default,,0000,0000,0000,,所以以后我提到周期 我说的是1MHz的机器周期 Dialogue: 0,0:17:07.73,0:17:13.75,Default,,0000,0000,0000,,所以这是一个拥有16位地址空间的8-Bit CPU Dialogue: 0,0:17:13.75,0:17:19.09,Default,,0000,0000,0000,,因为拥有16Bit的指针 所以一共也就是64KB的可见地址 Dialogue: 0,0:17:19.30,0:17:24.88,Default,,0000,0000,0000,,32KB的是ROM 直接来自卡带 映射到卡带 Dialogue: 0,0:17:25.10,0:17:28.99,Default,,0000,0000,0000,,然后在上方有一个Boot ROM 一会提 Dialogue: 0,0:17:29.20,0:17:36.09,Default,,0000,0000,0000,,VRAM也映射在这里 可选的外部RAM 以及内部RAM Dialogue: 0,0:17:36.36,0:17:40.18,Default,,0000,0000,0000,,没有使用的部分 要么没有东西 要么就是镜像已有的 Dialogue: 0,0:17:40.52,0:17:41.69,Default,,0000,0000,0000,,把最高地址的这些放大 Dialogue: 0,0:17:41.69,0:17:47.95,Default,,0000,0000,0000,,可以看到另外一页的OAM内存 就像是一种特殊用途的VRAM Dialogue: 0,0:17:48.16,0:17:50.58,Default,,0000,0000,0000,,独立于VRAM 一会会具体讲 Dialogue: 0,0:17:50.82,0:17:55.08,Default,,0000,0000,0000,,最后一页 也就是第0页 包括了IO部分 Dialogue: 0,0:17:55.31,0:17:57.62,Default,,0000,0000,0000,,所有的寄存器 声音的视频的 Dialogue: 0,0:17:57.88,0:18:05.22,Default,,0000,0000,0000,,还有127字节的HRAM 独立于其它的RAM Dialogue: 0,0:18:05.45,0:18:07.89,Default,,0000,0000,0000,,所以这代表游戏只能有32KB Dialogue: 0,0:18:08.10,0:18:10.66,Default,,0000,0000,0000,,有些游戏确实只需要32KB Dialogue: 0,0:18:10.83,0:18:13.56,Default,,0000,0000,0000,,比如说俄罗斯方块 就刚好挤进32KB 里面就一片芯片 Dialogue: 0,0:18:13.84,0:18:16.30,Default,,0000,0000,0000,,生产也很方便 Dialogue: 0,0:18:16.51,0:18:18.10,Default,,0000,0000,0000,,然后其它的卡带 Dialogue: 0,0:18:18.41,0:18:22.98,Default,,0000,0000,0000,,容量没有理论上限 但是实际上最大是到2MB Dialogue: 0,0:18:23.25,0:18:25.71,Default,,0000,0000,0000,,这个是128KB Dialogue: 0,0:18:25.93,0:18:29.74,Default,,0000,0000,0000,,实现的办法是 增加一个MBC (内存分页控制器) Dialogue: 0,0:18:29.96,0:18:32.60,Default,,0000,0000,0000,,一个特殊的可以切换分页的芯片 Dialogue: 0,0:18:32.82,0:18:35.34,Default,,0000,0000,0000,,这个在各种系统上都是很常见的做法 Dialogue: 0,0:18:35.56,0:18:40.91,Default,,0000,0000,0000,,这些控制器可以很不一样 但是实际上 大部分的工作方式是这样的 Dialogue: 0,0:18:41.13,0:18:45.93,Default,,0000,0000,0000,,最低16KB空间 永远映射到Bank0 Dialogue: 0,0:18:46.05,0:18:51.20,Default,,0000,0000,0000,,而16KB-32KB这部分可以映射到Bank1 Bank2等等 Dialogue: 0,0:18:52.96,0:18:57.11,Default,,0000,0000,0000,,切换分页的方法就是往一个地址空间内写入一些特定数值 Dialogue: 0,0:18:57.36,0:19:01.32,Default,,0000,0000,0000,,这些就会被MBC读取到 然后切换分页 Dialogue: 0,0:19:01.57,0:19:03.61,Default,,0000,0000,0000,,这点对于外部RAM也是一样的 Dialogue: 0,0:19:03.84,0:19:08.92,Default,,0000,0000,0000,,游戏卡带如果含有外置内存 比如用于保存游戏 Dialogue: 0,0:19:09.17,0:19:11.84,Default,,0000,0000,0000,,比如装有备份电池的内存 这也是保存游戏的唯一办法 Dialogue: 0,0:19:12.08,0:19:15.58,Default,,0000,0000,0000,,可以把外部内存映射在这里 一样的模型 Dialogue: 0,0:19:15.85,0:19:18.06,Default,,0000,0000,0000,,所以这个BootROM是什么 Dialogue: 0,0:19:18.33,0:19:22.44,Default,,0000,0000,0000,,CPU从内存地址0开始执行 Dialogue: 0,0:19:22.65,0:19:26.82,Default,,0000,0000,0000,,BootROM的作用就是显示这些东西 然后响一声 Dialogue: 0,0:19:27.29,0:19:29.25,Default,,0000,0000,0000,,BootROM是内置在GameBoy里面的 Dialogue: 0,0:19:29.51,0:19:32.90,Default,,0000,0000,0000,,花了一段时间这些代码才被提取出来 还是挺麻烦的 Dialogue: 0,0:19:33.07,0:19:34.25,Default,,0000,0000,0000,,(不是我完成的) Dialogue: 0,0:19:35.04,0:19:37.27,Default,,0000,0000,0000,,这个就是完整的BootROM Dialogue: 0,0:19:37.27,0:19:38.32,Default,,0000,0000,0000,,首先初始化RAM Dialogue: 0,0:19:38.32,0:19:39.69,Default,,0000,0000,0000,,初始化声音 Dialogue: 0,0:19:39.69,0:19:42.43,Default,,0000,0000,0000,,设置和解码显示在屏幕上的logo Dialogue: 0,0:19:42.65,0:19:44.76,Default,,0000,0000,0000,,卷动logo 播放声音 Dialogue: 0,0:19:44.99,0:19:48.65,Default,,0000,0000,0000,,然后就是有趣的部分 它对比logo Dialogue: 0,0:19:48.85,0:19:51.91,Default,,0000,0000,0000,,游戏卡带内需要有一份logo副本 Dialogue: 0,0:19:52.11,0:19:55.53,Default,,0000,0000,0000,,如果两者不一样 就不会继续开机 Dialogue: 0,0:19:55.74,0:20:00.33,Default,,0000,0000,0000,,这样任天堂就能控制什么游戏是给这个平台发行的 Dialogue: 0,0:20:00.53,0:20:02.18,Default,,0000,0000,0000,,游戏必须要内置这个logo Dialogue: 0,0:20:02.29,0:20:08.14,Default,,0000,0000,0000,,如果未经允许加入 那不单单是违反版权保护 而且还是违反商标保护 Dialogue: 0,0:20:09.58,0:20:13.14,Default,,0000,0000,0000,,最后是计算校验和 算是再一次确认 Dialogue: 0,0:20:13.14,0:20:15.55,Default,,0000,0000,0000,,否则你得拆出来吹吹卡带 吹吹机子 重新插一遍 Dialogue: 0,0:20:15.55,0:20:19.25,Default,,0000,0000,0000,,接着它关闭BootROM 继续执行 Dialogue: 0,0:20:19.37,0:20:26.87,Default,,0000,0000,0000,,这个logo 实际上是从卡带里面读取并且显示出来的 Dialogue: 0,0:20:27.09,0:20:30.02,Default,,0000,0000,0000,,如果不插卡带开机会看见这个 Dialogue: 0,0:20:30.74,0:20:34.28,Default,,0000,0000,0000,,但是这并不代表游戏开发商可以往里面装入任何logo Dialogue: 0,0:20:34.28,0:20:36.11,Default,,0000,0000,0000,,因为GameBoy会对比这个logo Dialogue: 0,0:20:36.14,0:20:38.08,Default,,0000,0000,0000,,如果logo错误就不会继续启动了 Dialogue: 0,0:20:39.33,0:20:41.86,Default,,0000,0000,0000,,因为没有清理代码 Dialogue: 0,0:20:42.03,0:20:44.11,Default,,0000,0000,0000,,没有重启系统或者其它事情 Dialogue: 0,0:20:44.11,0:20:47.16,Default,,0000,0000,0000,,所以有些游戏就直接开始调戏这个logo Dialogue: 0,0:20:47.39,0:20:48.32,Default,,0000,0000,0000,,直接在此之上继续 Dialogue: 0,0:20:48.55,0:20:50.78,Default,,0000,0000,0000,,demo也显然很喜欢调戏这个 Dialogue: 0,0:20:50.99,0:20:54.44,Default,,0000,0000,0000,,任天堂logo已经在屏幕上了 就对它做点啥吧(阴险 Dialogue: 0,0:20:59.34,0:21:00.03,Default,,0000,0000,0000,,很不错 Dialogue: 0,0:21:01.77,0:21:06.17,Default,,0000,0000,0000,,BootROM一直运行 直到最后一条指令关闭BootROM Dialogue: 0,0:21:06.38,0:21:11.72,Default,,0000,0000,0000,,这是即使是最低地址显示的也是游戏卡带的内容了 Dialogue: 0,0:21:11.93,0:21:13.54,Default,,0000,0000,0000,,它就继续从这里执行 Dialogue: 0,0:21:13.74,0:21:16.51,Default,,0000,0000,0000,,运行来自游戏中的下一条指令 Dialogue: 0,0:21:16.66,0:21:18.55,Default,,0000,0000,0000,,通常这里是一个跳转指令 Dialogue: 0,0:21:18.76,0:21:22.13,Default,,0000,0000,0000,,因为这其实是所谓的ROM头 按照要求就应该是这样的 Dialogue: 0,0:21:23.49,0:21:27.57,Default,,0000,0000,0000,,头部必须内置任天堂Logo 头部校验和 这是很重要的 Dialogue: 0,0:21:27.57,0:21:29.58,Default,,0000,0000,0000,,剩下的元数据就不重要了 Dialogue: 0,0:21:29.58,0:21:32.16,Default,,0000,0000,0000,,对于当时的游戏开发者来说什么很重要 Dialogue: 0,0:21:32.16,0:21:34.45,Default,,0000,0000,0000,,但是没有软件会真正检查这些内容 Dialogue: 0,0:21:34.45,0:21:38.04,Default,,0000,0000,0000,,在这之后 就可以放真正的游戏数据了 Dialogue: 0,0:21:39.26,0:21:42.94,Default,,0000,0000,0000,,还没讲到过的东西就是IO部分和HRAM了 Dialogue: 0,0:21:42.94,0:21:51.79,Default,,0000,0000,0000,,也就是在最高页 所谓的第0页 可以比较高效得操作 Dialogue: 0,0:21:51.97,0:21:55.68,Default,,0000,0000,0000,,最高的127字节是额外的内存 Dialogue: 0,0:21:55.86,0:22:00.10,Default,,0000,0000,0000,,剩下的 就是这些不同的设备 Dialogue: 0,0:22:00.29,0:22:02.74,Default,,0000,0000,0000,,这些是所有系统内的寄存器 Dialogue: 0,0:22:02.91,0:22:06.57,Default,,0000,0000,0000,,中断控制器 声音控制器 摇杆输入 串口传输 定时器 还有PPU Dialogue: 0,0:22:06.74,0:22:09.54,Default,,0000,0000,0000,,这些就是要讲的所有东西 Dialogue: 0,0:22:09.92,0:22:11.32,Default,,0000,0000,0000,,摇杆输入 Dialogue: 0,0:22:11.53,0:22:15.36,Default,,0000,0000,0000,,非常简单 这是所有GameBoy拥有的输入 Dialogue: 0,0:22:15.51,0:22:16.99,Default,,0000,0000,0000,,4个按钮 4个方向 Dialogue: 0,0:22:17.20,0:22:21.42,Default,,0000,0000,0000,,于是你会想 弄8个GPIO 这样就能实现了 Dialogue: 0,0:22:21.42,0:22:23.67,Default,,0000,0000,0000,,但是也可以用6个GPIO Dialogue: 0,0:22:24.23,0:22:26.39,Default,,0000,0000,0000,,2列4行 Dialogue: 0,0:22:26.53,0:22:32.68,Default,,0000,0000,0000,,你选择想要测试的行 然后知道这一行按下了什么按键 Dialogue: 0,0:22:32.72,0:22:34.62,Default,,0000,0000,0000,,这样就能用6个而不是8个 Dialogue: 0,0:22:35.14,0:22:36.72,Default,,0000,0000,0000,,按键就是这些 很简单 Dialogue: 0,0:22:37.45,0:22:38.84,Default,,0000,0000,0000,,串行数据传输 Dialogue: 0,0:22:39.13,0:22:42.29,Default,,0000,0000,0000,,你可以用一条联机线把两台GameBoy连在一起 Dialogue: 0,0:22:42.46,0:22:49.70,Default,,0000,0000,0000,,联机线其实就是 1条单向数据线 1条另外一个方向的数据线 1条时钟线 Dialogue: 0,0:22:49.92,0:22:54.41,Default,,0000,0000,0000,,两台GameBoy得确定谁发送时钟 谁接收时钟 Dialogue: 0,0:22:54.63,0:22:56.59,Default,,0000,0000,0000,,这些就是控制这些东西的位 Dialogue: 0,0:22:56.76,0:22:59.44,Default,,0000,0000,0000,,一个设置输出时钟 永远是8kHz Dialogue: 0,0:22:59.66,0:23:04.34,Default,,0000,0000,0000,,接收时钟范围很宽 可以从0一直到0.5MHz都能收到 Dialogue: 0,0:23:04.34,0:23:09.83,Default,,0000,0000,0000,,一旦传输开始 就会一位位移出字节 而且永远是全双工的 Dialogue: 0,0:23:11.68,0:23:12.73,Default,,0000,0000,0000,,定时器 Dialogue: 0,0:23:12.98,0:23:15.69,Default,,0000,0000,0000,,任何系统都得有个时钟 这个系统只有一个时钟 Dialogue: 0,0:23:17.35,0:23:21.08,Default,,0000,0000,0000,,TMA寄存器用来存放计数初值 Dialogue: 0,0:23:21.31,0:23:24.70,Default,,0000,0000,0000,,然后可以选择四种速度之一 Dialogue: 0,0:23:24.89,0:23:27.74,Default,,0000,0000,0000,,接着打开定时器 向上计时 Dialogue: 0,0:23:27.97,0:23:35.03,Default,,0000,0000,0000,,直到溢出 就会载入初值 然后可选的产生一个中断 Dialogue: 0,0:23:35.24,0:23:36.99,Default,,0000,0000,0000,,讲到中断 Dialogue: 0,0:23:37.16,0:23:40.12,Default,,0000,0000,0000,,中断控制器支持5种不同的中断 Dialogue: 0,0:23:40.29,0:23:45.21,Default,,0000,0000,0000,,V-Blank(场消隐) LCD状态 也就是和PPU相关 一会讲 Dialogue: 0,0:23:45.42,0:23:47.33,Default,,0000,0000,0000,,已经讲过的定时器 可以产生中断 Dialogue: 0,0:23:47.33,0:23:50.02,Default,,0000,0000,0000,,串口 可以在接受到数据的时候产生中断 Dialogue: 0,0:23:50.02,0:23:52.00,Default,,0000,0000,0000,,摇杆 可以在有按键按下的时候产生中断 Dialogue: 0,0:23:52.46,0:23:54.48,Default,,0000,0000,0000,,这个是中断启用寄存器 Dialogue: 0,0:23:54.66,0:23:56.30,Default,,0000,0000,0000,,一个中断标志寄存器 Dialogue: 0,0:23:56.54,0:23:59.10,Default,,0000,0000,0000,,可以看见有哪些中断还没有被处理 Dialogue: 0,0:23:59.29,0:24:02.67,Default,,0000,0000,0000,,这些是中断发生时会跳转的地址 Dialogue: 0,0:24:02.88,0:24:05.41,Default,,0000,0000,0000,,你不需要手动确定发生的是哪个中断 Dialogue: 0,0:24:05.58,0:24:07.14,Default,,0000,0000,0000,,因为直接跳转的就是不同的地址 Dialogue: 0,0:24:07.31,0:24:09.95,Default,,0000,0000,0000,,所以 声音控制器 Dialogue: 0,0:24:10.26,0:24:14.51,Default,,0000,0000,0000,,声音控制器的寄存器数量是最多的 Dialogue: 0,0:24:14.68,0:24:19.52,Default,,0000,0000,0000,,一共有四个声部 每个声部有自己的一组独立的寄存器 Dialogue: 0,0:24:19.70,0:24:21.50,Default,,0000,0000,0000,,这样看更为合理 Dialogue: 0,0:24:21.70,0:24:24.47,Default,,0000,0000,0000,,4个声部 每个声部5个寄存器 Dialogue: 0,0:24:26.45,0:24:29.89,Default,,0000,0000,0000,,每个寄存器有特定的含义 Dialogue: 0,0:24:31.61,0:24:33.37,Default,,0000,0000,0000,,但是含义只是大致的 Dialogue: 0,0:24:33.37,0:24:35.92,Default,,0000,0000,0000,,因为四个声道并不完全一样 Dialogue: 0,0:24:36.12,0:24:38.57,Default,,0000,0000,0000,,有两个很接近的 产生方波 Dialogue: 0,0:24:38.80,0:24:42.32,Default,,0000,0000,0000,,剩下两个一个是PCM采样 一个是杂波 Dialogue: 0,0:24:42.65,0:24:46.50,Default,,0000,0000,0000,,看位定义的话 有一定相似性 但是还是不一样 Dialogue: 0,0:24:46.61,0:24:49.57,Default,,0000,0000,0000,,具体通道有具体的定义 Dialogue: 0,0:24:50.25,0:24:53.11,Default,,0000,0000,0000,,先看看共通的一些参数 Dialogue: 0,0:24:53.29,0:24:56.38,Default,,0000,0000,0000,,每个声部都有一个开关位 也就是控制这个通道的开关 Dialogue: 0,0:24:56.61,0:24:59.15,Default,,0000,0000,0000,,你可以在某个时候关掉这个通道 Dialogue: 0,0:24:59.15,0:25:02.52,Default,,0000,0000,0000,,但是还有一个长度开关 以及长度设置寄存器 Dialogue: 0,0:25:02.73,0:25:05.68,Default,,0000,0000,0000,,所以比如你可以这么设置 在0.25秒后自动关闭 Dialogue: 0,0:25:06.80,0:25:09.79,Default,,0000,0000,0000,,然后先来看PCM采样声部的寄存器 也是最简单的一个 Dialogue: 0,0:25:11.29,0:25:14.79,Default,,0000,0000,0000,,这个声部的作用就是 可以播放任何的波形 Dialogue: 0,0:25:14.97,0:25:18.66,Default,,0000,0000,0000,,它有额外的16字节寄存器 Dialogue: 0,0:25:18.81,0:25:21.49,Default,,0000,0000,0000,,里面有32个位置 每个4位 Dialogue: 0,0:25:21.68,0:25:28.48,Default,,0000,0000,0000,,你可以在里面放任何你想要的波形 Dialogue: 0,0:25:28.69,0:25:29.78,Default,,0000,0000,0000,,这里是几个例子 Dialogue: 0,0:25:29.95,0:25:31.58,Default,,0000,0000,0000,,比如你可以产生一个锯齿波 Dialogue: 0,0:25:36.06,0:25:37.20,Default,,0000,0000,0000,,算是相当基本的波形 Dialogue: 0,0:25:37.43,0:25:38.97,Default,,0000,0000,0000,,也可以有正弦波 Dialogue: 0,0:25:44.01,0:25:46.11,Default,,0000,0000,0000,,或者是任何自定义的东西 Dialogue: 0,0:25:50.88,0:25:52.13,Default,,0000,0000,0000,,相当灵活 Dialogue: 0,0:25:52.80,0:25:54.34,Default,,0000,0000,0000,,然后有一个频率控制 Dialogue: 0,0:25:54.54,0:25:58.82,Default,,0000,0000,0000,,也就是控制采样的播放速度 Dialogue: 0,0:25:59.08,0:26:00.55,Default,,0000,0000,0000,,2位的音量 Dialogue: 0,0:26:00.79,0:26:03.72,Default,,0000,0000,0000,,音量可以在100% 50% 25%和静音之间控制 Dialogue: 0,0:26:05.20,0:26:10.07,Default,,0000,0000,0000,,另外两个 是很相似的两个方波声部 Dialogue: 0,0:26:10.27,0:26:13.16,Default,,0000,0000,0000,,这些位都是一样的,功能也一样 Dialogue: 0,0:26:13.42,0:26:18.08,Default,,0000,0000,0000,,你不能指定波形 波形是固定的 只能是方波 Dialogue: 0,0:26:18.09,0:26:19.59,Default,,0000,0000,0000,,就是只能是高或者低 Dialogue: 0,0:26:20.53,0:26:22.26,Default,,0000,0000,0000,,但是高低比例(占空比)可以不同 Dialogue: 0,0:26:22.26,0:26:25.78,Default,,0000,0000,0000,,这两个位就是控制占空比的 Dialogue: 0,0:26:27.93,0:26:30.67,Default,,0000,0000,0000,,可以设置12.5%高 剩下的低 Dialogue: 0,0:26:33.39,0:26:34.24,Default,,0000,0000,0000,,25% Dialogue: 0,0:26:36.60,0:26:37.35,Default,,0000,0000,0000,,50% Dialogue: 0,0:26:37.35,0:26:40.06,Default,,0000,0000,0000,,75%听起来应该和25%一样,只是反相了 Dialogue: 0,0:26:43.32,0:26:46.51,Default,,0000,0000,0000,,这个是两个声部都支持的功能 Dialogue: 0,0:26:46.76,0:26:49.49,Default,,0000,0000,0000,,另外有一个功能叫音量扫频 (Volume Sweep,翻译不准确,暂时想不到更好的) Dialogue: 0,0:26:49.51,0:26:52.30,Default,,0000,0000,0000,,就是音量可以增高或者降低 Dialogue: 0,0:26:52.46,0:26:56.26,Default,,0000,0000,0000,,降低就是模拟乐器的情况 Dialogue: 0,0:26:58.63,0:27:01.10,Default,,0000,0000,0000,,或者也能增高 效果比较有趣 Dialogue: 0,0:27:04.53,0:27:10.46,Default,,0000,0000,0000,,然后 只有第一个声部有扫频功能 Dialogue: 0,0:27:10.66,0:27:12.42,Default,,0000,0000,0000,,可以升高 Dialogue: 0,0:27:15.24,0:27:16.19,Default,,0000,0000,0000,,也可以降低 Dialogue: 0,0:27:18.69,0:27:21.16,Default,,0000,0000,0000,,所以可以注意到主要是用于音效的 Dialogue: 0,0:27:21.33,0:27:22.62,Default,,0000,0000,0000,,更多的音效例子 Dialogue: 0,0:27:25.44,0:27:26.93,Default,,0000,0000,0000,,这就是可以实现的效果 Dialogue: 0,0:27:27.62,0:27:30.43,Default,,0000,0000,0000,,然后还有第四个杂波通道 Dialogue: 0,0:27:30.61,0:27:35.58,Default,,0000,0000,0000,,就是一个只能产生伪随机数的移位寄存器 Dialogue: 0,0:27:36.03,0:27:41.02,Default,,0000,0000,0000,,根据你设置的15bit模式或者7bit模式 Dialogue: 0,0:27:41.24,0:27:45.39,Default,,0000,0000,0000,,他能产生两种不同的波形 Dialogue: 0,0:27:48.19,0:27:49.35,Default,,0000,0000,0000,,这是15bit模式 Dialogue: 0,0:27:51.57,0:27:52.69,Default,,0000,0000,0000,,这是7bit模式 Dialogue: 0,0:27:54.14,0:27:55.58,Default,,0000,0000,0000,,这些是所有的寄存器 Dialogue: 0,0:27:56.06,0:28:00.04,Default,,0000,0000,0000,,4个声部的寄存器 3个通用寄存器 Dialogue: 0,0:28:00.39,0:28:03.56,Default,,0000,0000,0000,,这个可以设置左声道和右声道的音量 Dialogue: 0,0:28:03.73,0:28:07.52,Default,,0000,0000,0000,,有趣的是卡带可以有自己的音频控制器 Dialogue: 0,0:28:07.74,0:28:10.85,Default,,0000,0000,0000,,可以产生接到这个上面的音频信号 Dialogue: 0,0:28:11.02,0:28:12.21,Default,,0000,0000,0000,,但是没有游戏做过这种事情 Dialogue: 0,0:28:12.81,0:28:20.85,Default,,0000,0000,0000,,然后还有一个寄存器 可以设置一个通道是接到左声道还是右声道 或者都接、都不接 Dialogue: 0,0:28:21.04,0:28:23.06,Default,,0000,0000,0000,,然后有一个电源开关 Dialogue: 0,0:28:23.20,0:28:26.56,Default,,0000,0000,0000,,关掉音频部分可以减少约30%的电力消耗 Dialogue: 0,0:28:28.58,0:28:33.48,Default,,0000,0000,0000,,然后 GameBoy的声音系统不单单被用于游戏 Dialogue: 0,0:28:33.76,0:28:38.54,Default,,0000,0000,0000,,人们现在还在GB上用Little Sound DJ一类的软件编曲 Dialogue: 0,0:28:38.74,0:28:40.54,Default,,0000,0000,0000,,我展示一个简单的例子 Dialogue: 0,0:29:17.13,0:29:18.14,Default,,0000,0000,0000,,音频就到此为止 Dialogue: 0,0:29:18.71,0:29:21.19,Default,,0000,0000,0000,,我们来谈谈Pixel Processing Unit (像素处理单元/PPU) Dialogue: 0,0:29:21.61,0:29:25.45,Default,,0000,0000,0000,,PPU就是产生图形的部分 拥有12个寄存器 Dialogue: 0,0:29:25.59,0:29:26.51,Default,,0000,0000,0000,,并不是很多 Dialogue: 0,0:29:27.34,0:29:28.95,Default,,0000,0000,0000,,首先来看看规格 Dialogue: 0,0:29:29.29,0:29:32.43,Default,,0000,0000,0000,,在之前讲过,160*144像素,不是很多 Dialogue: 0,0:29:32.63,0:29:36.22,Default,,0000,0000,0000,,4级灰度 其实更接近于4级不同的绿色 Dialogue: 0,0:29:36.40,0:29:39.08,Default,,0000,0000,0000,,当然后续的GameBoy要好得多 Dialogue: 0,0:29:39.27,0:29:41.46,Default,,0000,0000,0000,,所有屏幕上的东西都是以8*8像素的方格为单位的 Dialogue: 0,0:29:41.66,0:29:44.44,Default,,0000,0000,0000,,屏幕上有一定数量的方格 还有一些精灵 Dialogue: 0,0:29:44.61,0:29:46.14,Default,,0000,0000,0000,,这些东西都得装进8KB的显存 Dialogue: 0,0:29:46.34,0:29:49.40,Default,,0000,0000,0000,,具体解释下这个8*8像素方格 Dialogue: 0,0:29:49.64,0:29:51.44,Default,,0000,0000,0000,,我们看一下俄罗斯方块的游戏画面 Dialogue: 0,0:29:51.64,0:29:54.35,Default,,0000,0000,0000,,所有东西都是基于这些方块的 Dialogue: 0,0:29:54.56,0:30:00.71,Default,,0000,0000,0000,,塞尔达也是一样 画上网格线就能看见重复的图案 而且都是和网格线对齐的 Dialogue: 0,0:30:00.90,0:30:06.24,Default,,0000,0000,0000,,超级马里奥大陆也是很明显 因为没有很多不同的方格 Dialogue: 0,0:30:06.51,0:30:09.40,Default,,0000,0000,0000,,甚至是像Donkey Kong Land这样的游戏 Dialogue: 0,0:30:09.64,0:30:12.18,Default,,0000,0000,0000,,在画上网格后还是能看出来的 Dialogue: 0,0:30:12.44,0:30:14.16,Default,,0000,0000,0000,,可以看见重复对齐的图案 Dialogue: 0,0:30:14.36,0:30:16.59,Default,,0000,0000,0000,,尽管他们很好地隐藏了这一点 Dialogue: 0,0:30:17.84,0:30:21.02,Default,,0000,0000,0000,,有些游戏干脆就利用这个特性来设计 Dialogue: 0,0:30:21.02,0:30:23.81,Default,,0000,0000,0000,,在Turrican里面干脆就用方块做了个动画 Dialogue: 0,0:30:24.54,0:30:26.74,Default,,0000,0000,0000,,我们来看看方格是什么样的 Dialogue: 0,0:30:27.07,0:30:30.31,Default,,0000,0000,0000,,一个方格尺寸是8*8 可以有4种颜色 Dialogue: 0,0:30:32.15,0:30:35.20,Default,,0000,0000,0000,,4种颜色的编码就是00 01 10和11 Dialogue: 0,0:30:36.04,0:30:40.24,Default,,0000,0000,0000,,把这个叠加到像素上看看编码是如何完成的 Dialogue: 0,0:30:40.50,0:30:42.90,Default,,0000,0000,0000,,看第一行 直接当成一个二进制数读 Dialogue: 0,0:30:43.07,0:30:46.92,Default,,0000,0000,0000,,于是就是 02 FF 一行像素需要2个字节 Dialogue: 0,0:30:47.14,0:30:50.71,Default,,0000,0000,0000,,整个下来一个方块就是16字节 Dialogue: 0,0:30:51.98,0:30:56.46,Default,,0000,0000,0000,,你可能注意到了这个颜色的排序比较奇怪 Dialogue: 0,0:30:56.68,0:30:58.98,Default,,0000,0000,0000,,这是因为调色板是可以自定的 Dialogue: 0,0:30:59.25,0:31:00.87,Default,,0000,0000,0000,,我可以选择任何想要的调色板 Dialogue: 0,0:31:00.87,0:31:04.21,Default,,0000,0000,0000,,系统内对于这些背景方块有个2位到2位的映射 Dialogue: 0,0:31:05.52,0:31:09.85,Default,,0000,0000,0000,,原生的表示方法是 00表示白 11表示黑 Dialogue: 0,0:31:10.24,0:31:12.98,Default,,0000,0000,0000,,我可以选择任意的这种的调色板 Dialogue: 0,0:31:13.15,0:31:16.18,Default,,0000,0000,0000,,如果有需要 我也可以选择一样的颜色 Dialogue: 0,0:31:17.75,0:31:19.62,Default,,0000,0000,0000,,系统内一共支持256个方块 Dialogue: 0,0:31:19.86,0:31:22.04,Default,,0000,0000,0000,,看这个设置 你认出是什么游戏了吗 Dialogue: 0,0:31:22.24,0:31:24.04,Default,,0000,0000,0000,,这是俄罗斯方块 Dialogue: 0,0:31:24.41,0:31:26.58,Default,,0000,0000,0000,,如果你不认识底部那些跳舞的人 Dialogue: 0,0:31:26.77,0:31:28.44,Default,,0000,0000,0000,,说明你没有通关过俄罗斯方块 Dialogue: 0,0:31:31.44,0:31:32.44,Default,,0000,0000,0000,,这是塞尔达 Dialogue: 0,0:31:33.74,0:31:37.26,Default,,0000,0000,0000,,这是超级马里奥大陆 只使用了128个方块 Dialogue: 0,0:31:39.03,0:31:40.86,Default,,0000,0000,0000,,有人认识这个吗? Dialogue: 0,0:31:42.95,0:31:44.99,Default,,0000,0000,0000,,这个只是一个拼图 Dialogue: 0,0:31:46.17,0:31:47.12,Default,,0000,0000,0000,,是网球 Dialogue: 0,0:31:50.33,0:31:55.32,Default,,0000,0000,0000,,20*18个方块填满了整个屏幕 Dialogue: 0,0:31:55.51,0:31:56.83,Default,,0000,0000,0000,,但是其实事情不完全是这样 Dialogue: 0,0:31:57.02,0:32:01.62,Default,,0000,0000,0000,,在视频内存中 有32*32方块 Dialogue: 0,0:32:01.80,0:32:03.02,Default,,0000,0000,0000,,这才是完整的背景映射 Dialogue: 0,0:32:03.22,0:32:05.64,Default,,0000,0000,0000,,屏幕上能看见的只是一个区域(Viewport) Dialogue: 0,0:32:07.25,0:32:12.14,Default,,0000,0000,0000,,256*256个像素还是相当方便的数字 Dialogue: 0,0:32:12.67,0:32:16.68,Default,,0000,0000,0000,,卷动很方便,只要移动这个区域就可以了 Dialogue: 0,0:32:17.60,0:32:23.02,Default,,0000,0000,0000,,使用这个模拟器就能很清楚得看到背景中发生了什么事情 Dialogue: 0,0:32:23.26,0:32:24.94,Default,,0000,0000,0000,,以及可视区域是如何移动的 Dialogue: 0,0:32:25.12,0:32:28.81,Default,,0000,0000,0000,,其实就像是一个摄像机,在32*32的映射中移动 Dialogue: 0,0:32:29.79,0:32:33.59,Default,,0000,0000,0000,,但是这种方法只适用于最大地图只有32*32的游戏 Dialogue: 0,0:32:33.73,0:32:35.77,Default,,0000,0000,0000,,但是那种需要无限卷动的游戏怎么办 Dialogue: 0,0:32:35.96,0:32:37.61,Default,,0000,0000,0000,,比如超级马里奥大陆 Dialogue: 0,0:32:37.83,0:32:40.37,Default,,0000,0000,0000,,最多可以有这么多的列 Dialogue: 0,0:32:40.54,0:32:42.40,Default,,0000,0000,0000,,可以把区域移动到这里 Dialogue: 0,0:32:42.53,0:32:45.07,Default,,0000,0000,0000,,但是到最后怎么办 Dialogue: 0,0:32:45.27,0:32:47.51,Default,,0000,0000,0000,,它会直接卷到左边 Dialogue: 0,0:32:47.76,0:32:52.11,Default,,0000,0000,0000,,如果我们能在显示出来之前重绘这些画面 Dialogue: 0,0:32:52.28,0:32:53.28,Default,,0000,0000,0000,,就可以拥有无限的世界大小 Dialogue: 0,0:32:54.04,0:32:56.44,Default,,0000,0000,0000,,在模拟器里就看得很清楚了 Dialogue: 0,0:32:56.64,0:33:01.52,Default,,0000,0000,0000,,在屏幕显示不到的地方会不断刷新新的地图 Dialogue: 0,0:33:01.71,0:33:03.56,Default,,0000,0000,0000,,对于二维也是一个道理 Dialogue: 0,0:33:03.56,0:33:05.06,Default,,0000,0000,0000,,这是Donkey Kong Land Dialogue: 0,0:33:05.06,0:33:06.52,Default,,0000,0000,0000,,这个看起来很奇怪 Dialogue: 0,0:33:06.52,0:33:11.23,Default,,0000,0000,0000,,只在需要显示的地方绘制新的地图 Dialogue: 0,0:33:14.07,0:33:16.64,Default,,0000,0000,0000,,这是我们已经谈论过的一个图层 Dialogue: 0,0:33:18.67,0:33:19.70,Default,,0000,0000,0000,,背景图层 Dialogue: 0,0:33:19.84,0:33:23.08,Default,,0000,0000,0000,,除了背景外 还能放一层图像 Dialogue: 0,0:33:23.25,0:33:24.29,Default,,0000,0000,0000,,窗口 Dialogue: 0,0:33:24.46,0:33:25.29,Default,,0000,0000,0000,,可以直接覆盖 Dialogue: 0,0:33:25.29,0:33:26.71,Default,,0000,0000,0000,,也可以放在任意地方 Dialogue: 0,0:33:26.71,0:33:28.39,Default,,0000,0000,0000,,有个XY坐标 Dialogue: 0,0:33:28.39,0:33:31.14,Default,,0000,0000,0000,,他会从起始坐标开始向右下方绘制 Dialogue: 0,0:33:31.36,0:33:33.11,Default,,0000,0000,0000,,然而没有透明支持 Dialogue: 0,0:33:33.29,0:33:36.01,Default,,0000,0000,0000,,通常的用法就是放到右边 Dialogue: 0,0:33:36.19,0:33:37.70,Default,,0000,0000,0000,,或者放到下面 Dialogue: 0,0:33:37.84,0:33:40.61,Default,,0000,0000,0000,,因为这个是不受卷动影响的 Dialogue: 0,0:33:41.94,0:33:46.69,Default,,0000,0000,0000,,显然这个功能对于屏幕下方的分数显示来说是很必要的 Dialogue: 0,0:33:46.73,0:33:49.10,Default,,0000,0000,0000,,对于游戏来说非常简单好用的功能 Dialogue: 0,0:33:49.90,0:33:51.81,Default,,0000,0000,0000,,当然也能放在右边 Dialogue: 0,0:33:52.03,0:33:55.57,Default,,0000,0000,0000,,这些是GBC游戏 但是不影响 在GB上也能玩 Dialogue: 0,0:33:57.30,0:34:00.37,Default,,0000,0000,0000,,然后在背景和窗口层之上还有一个图层 Dialogue: 0,0:34:00.37,0:34:01.42,Default,,0000,0000,0000,,就是精灵层 Dialogue: 0,0:34:01.62,0:34:06.08,Default,,0000,0000,0000,,精灵就是放在屏幕上的不用受限于8*8方格的物体 Dialogue: 0,0:34:06.08,0:34:07.55,Default,,0000,0000,0000,,可以自由摆放 Dialogue: 0,0:34:07.74,0:34:09.80,Default,,0000,0000,0000,,现在屏幕上有3个精灵 Dialogue: 0,0:34:09.91,0:34:11.53,Default,,0000,0000,0000,,任天堂把它们叫做 对象,OBJ Dialogue: 0,0:34:12.17,0:34:14.79,Default,,0000,0000,0000,,但是我还是继续叫他们精灵 因为就是精灵 Dialogue: 0,0:34:15.02,0:34:16.84,Default,,0000,0000,0000,,就直接拿这个蘑菇举例吧 Dialogue: 0,0:34:17.03,0:34:20.17,Default,,0000,0000,0000,,每个精灵都有自己的属性 Dialogue: 0,0:34:20.34,0:34:23.61,Default,,0000,0000,0000,,系统内有个 OAM 也就是对象属性映射表 Dialogue: 0,0:34:23.85,0:34:25.10,Default,,0000,0000,0000,,这个就是一个OAM记录 Dialogue: 0,0:34:25.31,0:34:26.70,Default,,0000,0000,0000,,含有以下值 Dialogue: 0,0:34:26.87,0:34:28.12,Default,,0000,0000,0000,,第一个是X位置 Dialogue: 0,0:34:28.29,0:34:30.85,Default,,0000,0000,0000,,把它放到屏幕的左边 Dialogue: 0,0:34:31.03,0:34:34.44,Default,,0000,0000,0000,,你可能会以为应该横向坐标为0 Dialogue: 0,0:34:34.67,0:34:35.68,Default,,0000,0000,0000,,但是不是 是8 Dialogue: 0,0:34:35.86,0:34:36.56,Default,,0000,0000,0000,,为什么呢 Dialogue: 0,0:34:36.67,0:34:37.69,Default,,0000,0000,0000,,因为如果你把它放在4 Dialogue: 0,0:34:37.84,0:34:38.58,Default,,0000,0000,0000,,他就在这 Dialogue: 0,0:34:38.58,0:34:39.48,Default,,0000,0000,0000,,如果设置成0 Dialogue: 0,0:34:39.48,0:34:41.19,Default,,0000,0000,0000,,那就看不见了 因为宽度是8 Dialogue: 0,0:34:41.28,0:34:42.44,Default,,0000,0000,0000,,需要有一种方法能让它进入屏幕 Dialogue: 0,0:34:42.96,0:34:45.76,Default,,0000,0000,0000,,对于屏幕顶端的情况也是一样的 Dialogue: 0,0:34:45.93,0:34:49.45,Default,,0000,0000,0000,,但是你看现在的Y坐标是16 Dialogue: 0,0:34:49.45,0:34:58.39,Default,,0000,0000,0000,,因为一个精灵最高可以有16像素高 Dialogue: 0,0:34:58.60,0:35:01.68,Default,,0000,0000,0000,,把它放到一个自然的位置 Dialogue: 0,0:35:01.92,0:35:05.93,Default,,0000,0000,0000,,下一个问题就是应该长什么样 Dialogue: 0,0:35:06.16,0:35:08.39,Default,,0000,0000,0000,,首先看见是一个8*8的方格 Dialogue: 0,0:35:08.39,0:35:09.36,Default,,0000,0000,0000,,和之前的方格是一样的编码 Dialogue: 0,0:35:09.36,0:35:11.26,Default,,0000,0000,0000,,只是这个还带有透明色 Dialogue: 0,0:35:11.26,0:35:13.64,Default,,0000,0000,0000,,所以00 表示透明 Dialogue: 0,0:35:13.83,0:35:16.71,Default,,0000,0000,0000,,因为是一样的编码 所以也是一样的方格 Dialogue: 0,0:35:16.87,0:35:20.67,Default,,0000,0000,0000,,而且系统内也有256个方格位可供使用 Dialogue: 0,0:35:20.85,0:35:23.17,Default,,0000,0000,0000,,你看现在是方块编号0x90 Dialogue: 0,0:35:24.32,0:35:26.61,Default,,0000,0000,0000,,剩下一个是 X翻转 选项 Dialogue: 0,0:35:27.09,0:35:32.31,Default,,0000,0000,0000,,所以你没有必要为 向左走 和 向右走 的蘑菇单独存两个方块 Dialogue: 0,0:35:32.50,0:35:35.42,Default,,0000,0000,0000,,水平翻转一下 就有向右走的了 Dialogue: 0,0:35:35.55,0:35:37.65,Default,,0000,0000,0000,,垂直翻转一下 就有死蘑菇了 Dialogue: 0,0:35:37.82,0:35:41.74,Default,,0000,0000,0000,,同时垂直和水平翻转 就有向右走的死蘑菇啦~ Dialogue: 0,0:35:42.73,0:35:44.88,Default,,0000,0000,0000,,调回来 Dialogue: 0,0:35:45.08,0:35:47.01,Default,,0000,0000,0000,,下一个是调色板 Dialogue: 0,0:35:47.17,0:35:52.20,Default,,0000,0000,0000,,因为其中一种的颜色表示的是透明 Dialogue: 0,0:35:52.40,0:35:55.29,Default,,0000,0000,0000,,所以只剩下3种颜色可以选择 Dialogue: 0,0:35:55.49,0:36:00.63,Default,,0000,0000,0000,,他们不想强制固定这三种颜色 Dialogue: 0,0:36:00.80,0:36:05.22,Default,,0000,0000,0000,,所以你可以在四种颜色里面挑3种想要的 Dialogue: 0,0:36:05.38,0:36:07.86,Default,,0000,0000,0000,,而且不同的精灵不需要使用同样的3种颜色 Dialogue: 0,0:36:08.06,0:36:10.44,Default,,0000,0000,0000,,因为系统内可以有两个调色板 Dialogue: 0,0:36:10.66,0:36:14.76,Default,,0000,0000,0000,,所以才有这个位 可以选择是调色板0还是调色板1 Dialogue: 0,0:36:14.88,0:36:18.46,Default,,0000,0000,0000,,调色板1和0分别效果就是这样 Dialogue: 0,0:36:19.64,0:36:21.03,Default,,0000,0000,0000,,剩下一个是优先级 Dialogue: 0,0:36:21.35,0:36:25.03,Default,,0000,0000,0000,,就是精灵碰到背景时如何绘图 Dialogue: 0,0:36:26.00,0:36:28.12,Default,,0000,0000,0000,,如果优先级是1就有趣了 Dialogue: 0,0:36:28.28,0:36:30.31,Default,,0000,0000,0000,,它会画在这些白色像素之上 Dialogue: 0,0:36:30.44,0:36:34.34,Default,,0000,0000,0000,,但是在所有不是白色的像素后面 Dialogue: 0,0:36:34.41,0:36:36.11,Default,,0000,0000,0000,,当然白色并不是一个什么特殊颜色 Dialogue: 0,0:36:36.20,0:36:41.70,Default,,0000,0000,0000,,只是指背景调色板里的0号颜色 Dialogue: 0,0:36:41.82,0:36:46.41,Default,,0000,0000,0000,,所以改调色板 就能让蘑菇显示在任意颜色之上 Dialogue: 0,0:36:46.56,0:36:50.19,Default,,0000,0000,0000,,优先级0的话就会绘制在任何东西之上 Dialogue: 0,0:36:50.19,0:36:51.87,Default,,0000,0000,0000,,当然不包括透明像素 Dialogue: 0,0:36:53.39,0:36:55.34,Default,,0000,0000,0000,,然后就是精灵之间的优先级问题 Dialogue: 0,0:36:55.50,0:36:57.06,Default,,0000,0000,0000,,这个没有办法自己设置 Dialogue: 0,0:36:57.06,0:36:57.93,Default,,0000,0000,0000,,这个是固定的 Dialogue: 0,0:36:57.98,0:37:01.27,Default,,0000,0000,0000,,现在蘑菇在正方形之上 Dialogue: 0,0:37:01.41,0:37:04.69,Default,,0000,0000,0000,,因为它的横向坐标比正方形小 Dialogue: 0,0:37:04.83,0:37:06.76,Default,,0000,0000,0000,,一旦达到一样的坐标 Dialogue: 0,0:37:06.80,0:37:09.27,Default,,0000,0000,0000,,精灵编号小的显示在上 Dialogue: 0,0:37:09.27,0:37:14.03,Default,,0000,0000,0000,,因为精灵在内存中也是一个数组 存前面的画上面 Dialogue: 0,0:37:14.03,0:37:20.77,Default,,0000,0000,0000,,然而一旦正方形的X坐标小于蘑菇的X坐标 就会画在上面 Dialogue: 0,0:37:20.90,0:37:24.49,Default,,0000,0000,0000,,一部分游戏中穿透其它精灵的时候 就能看到这种现象 Dialogue: 0,0:37:25.81,0:37:30.02,Default,,0000,0000,0000,,系统支持最多40个精灵 屏幕上最多也是能放40个 Dialogue: 0,0:37:30.44,0:37:31.66,Default,,0000,0000,0000,,但是还有一个限制 Dialogue: 0,0:37:32.01,0:37:33.78,Default,,0000,0000,0000,,每一行最多只能有10个 Dialogue: 0,0:37:33.91,0:37:35.36,Default,,0000,0000,0000,,比如这里有11个 Dialogue: 0,0:37:35.51,0:37:37.38,Default,,0000,0000,0000,,10个是按照一行像素计算的 Dialogue: 0,0:37:37.46,0:37:39.06,Default,,0000,0000,0000,,所以这些像素就不会被显示出来 Dialogue: 0,0:37:39.93,0:37:42.37,Default,,0000,0000,0000,,或者是下面两行 Dialogue: 0,0:37:42.40,0:37:45.31,Default,,0000,0000,0000,,这个不是讲从左到右的第十个 Dialogue: 0,0:37:45.49,0:37:50.73,Default,,0000,0000,0000,,而是按照精灵的编号来决定的 Dialogue: 0,0:37:51.82,0:37:54.25,Default,,0000,0000,0000,,所以这是一个完整的OAM记录 Dialogue: 0,0:37:54.43,0:37:55.91,Default,,0000,0000,0000,,一共4个字节 Dialogue: 0,0:37:56.06,0:37:58.08,Default,,0000,0000,0000,,这是内存中的一个OAM记录 Dialogue: 0,0:37:58.24,0:38:01.48,Default,,0000,0000,0000,,FE00就是存储这些记录的起始地址 Dialogue: 0,0:38:01.62,0:38:03.78,Default,,0000,0000,0000,,一共有40个记录 里面能存40个精灵 Dialogue: 0,0:38:03.78,0:38:05.40,Default,,0000,0000,0000,,整个这个叫做OAM内存 Dialogue: 0,0:38:05.40,0:38:08.71,Default,,0000,0000,0000,,就是一个存在这个位置的专用内存 Dialogue: 0,0:38:08.71,0:38:10.42,Default,,0000,0000,0000,,并不是显存的一部分 Dialogue: 0,0:38:11.66,0:38:13.43,Default,,0000,0000,0000,,还有一件事情 Dialogue: 0,0:38:13.65,0:38:15.38,Default,,0000,0000,0000,,就是即使是小马里奥 Dialogue: 0,0:38:15.54,0:38:17.91,Default,,0000,0000,0000,,也超过了8*8 Dialogue: 0,0:38:18.08,0:38:20.57,Default,,0000,0000,0000,,你可以用4个精灵来实现 Dialogue: 0,0:38:20.73,0:38:21.83,Default,,0000,0000,0000,,这也是游戏里的做法 Dialogue: 0,0:38:21.96,0:38:23.11,Default,,0000,0000,0000,,但是还有一个模式 Dialogue: 0,0:38:23.11,0:38:25.48,Default,,0000,0000,0000,,可以拥有16像素高的精灵 Dialogue: 0,0:38:25.48,0:38:27.00,Default,,0000,0000,0000,,但是这个设定是全局的 Dialogue: 0,0:38:27.00,0:38:30.37,Default,,0000,0000,0000,,整个游戏都得使用16像素高的精灵 Dialogue: 0,0:38:31.04,0:38:33.08,Default,,0000,0000,0000,,所以已经见过3层了 Dialogue: 0,0:38:33.23,0:38:37.66,Default,,0000,0000,0000,,还有一件事情是 屏幕是可以被彻底关闭的 Dialogue: 0,0:38:37.78,0:38:39.55,Default,,0000,0000,0000,,这样就有第五种颜色了(强行) Dialogue: 0,0:38:39.70,0:38:42.39,Default,,0000,0000,0000,,稍微比白色位再淡一点 Dialogue: 0,0:38:42.54,0:38:46.08,Default,,0000,0000,0000,,没啥用 因为得把屏幕关掉 Dialogue: 0,0:38:46.18,0:38:49.16,Default,,0000,0000,0000,,一旦打开屏幕但是不画任何东西 Dialogue: 0,0:38:49.35,0:38:50.54,Default,,0000,0000,0000,,就是白色 Dialogue: 0,0:38:50.54,0:38:53.46,Default,,0000,0000,0000,,然后打开背景层 比如说要显示个淡灰色 Dialogue: 0,0:38:53.46,0:38:55.69,Default,,0000,0000,0000,,然后就完全代替了这个颜色 Dialogue: 0,0:38:55.69,0:38:56.92,Default,,0000,0000,0000,,再画个窗口 Dialogue: 0,0:38:57.16,0:38:58.54,Default,,0000,0000,0000,,注意没有透明 Dialogue: 0,0:38:58.66,0:39:01.37,Default,,0000,0000,0000,,还能在上面画精灵 Dialogue: 0,0:39:01.50,0:39:05.10,Default,,0000,0000,0000,,但是注意精灵和窗口的颜色就无法区分了 Dialogue: 0,0:39:05.25,0:39:07.07,Default,,0000,0000,0000,,所以说窗口上没有裁剪一类的事情 Dialogue: 0,0:39:08.56,0:39:11.89,Default,,0000,0000,0000,,所以内存映射是怎么样的 Dialogue: 0,0:39:12.06,0:39:13.77,Default,,0000,0000,0000,,4KB的精灵方块 Dialogue: 0,0:39:13.77,0:39:16.16,Default,,0000,0000,0000,,4KB的背景方块 Dialogue: 0,0:39:16.33,0:39:19.12,Default,,0000,0000,0000,,1KB的背景映射表 Dialogue: 0,0:39:19.22,0:39:20.74,Default,,0000,0000,0000,,32*32 Dialogue: 0,0:39:20.84,0:39:22.96,Default,,0000,0000,0000,,1KB的窗口映射表 Dialogue: 0,0:39:22.99,0:39:24.38,Default,,0000,0000,0000,,这不是最高效的表示方法 Dialogue: 0,0:39:24.38,0:39:27.28,Default,,0000,0000,0000,,但是他们这么做了 因为方便 Dialogue: 0,0:39:27.42,0:39:30.23,Default,,0000,0000,0000,,但是我们只有8KB的显存 Dialogue: 0,0:39:30.35,0:39:34.23,Default,,0000,0000,0000,,放个精灵方块和背景方块 就用完了 Dialogue: 0,0:39:34.66,0:39:36.14,Default,,0000,0000,0000,,换种方法 Dialogue: 0,0:39:36.14,0:39:39.75,Default,,0000,0000,0000,,先放上精灵方块 然后在最后放上背景和窗口映射 Dialogue: 0,0:39:39.75,0:39:41.38,Default,,0000,0000,0000,,背景方块怎么办 Dialogue: 0,0:39:41.38,0:39:42.56,Default,,0000,0000,0000,,就让它们重合 Dialogue: 0,0:39:43.56,0:39:46.58,Default,,0000,0000,0000,,有不同的配置 3个位 Dialogue: 0,0:39:46.62,0:39:48.37,Default,,0000,0000,0000,,可以让它们完全重合 Dialogue: 0,0:39:48.37,0:39:49.48,Default,,0000,0000,0000,,也可以只重合一部分 Dialogue: 0,0:39:49.64,0:39:52.40,Default,,0000,0000,0000,,这些也可以交换或者重合 Dialogue: 0,0:39:53.03,0:39:54.57,Default,,0000,0000,0000,,重合表示什么意思 Dialogue: 0,0:39:54.61,0:40:00.79,Default,,0000,0000,0000,,这个情况就是精灵方块和背景方块完全重合 Dialogue: 0,0:40:00.79,0:40:03.35,Default,,0000,0000,0000,,可以共享完全相同的方块 Dialogue: 0,0:40:03.35,0:40:05.03,Default,,0000,0000,0000,,但是也可以这么放 Dialogue: 0,0:40:05.03,0:40:11.54,Default,,0000,0000,0000,,前128个就是精灵专用 后128个就是背景专用 Dialogue: 0,0:40:11.54,0:40:14.57,Default,,0000,0000,0000,,中间128个共享 Dialogue: 0,0:40:14.57,0:40:16.47,Default,,0000,0000,0000,,比如这个超级马里奥大陆 Dialogue: 0,0:40:16.66,0:40:20.11,Default,,0000,0000,0000,,前2/3都用于精灵了 Dialogue: 0,0:40:20.34,0:40:22.02,Default,,0000,0000,0000,,剩下的1/3被用于背景 Dialogue: 0,0:40:24.47,0:40:26.67,Default,,0000,0000,0000,,下一个部分是横向计时 Dialogue: 0,0:40:30.25,0:40:32.87,Default,,0000,0000,0000,,在基于CRT的机器当中 Dialogue: 0,0:40:33.01,0:40:38.27,Default,,0000,0000,0000,,这就是CRT显示图像的慢动作效果 Dialogue: 0,0:40:38.84,0:40:41.67,Default,,0000,0000,0000,,从头到底 从左到右 Dialogue: 0,0:40:43.05,0:40:44.50,Default,,0000,0000,0000,,对于GameBoy也是一样的 Dialogue: 0,0:40:44.69,0:40:47.22,Default,,0000,0000,0000,,它以60Hz的速度不停地扫描 Dialogue: 0,0:40:47.40,0:40:48.88,Default,,0000,0000,0000,,从上到下 一行一行 Dialogue: 0,0:40:48.88,0:40:49.67,Default,,0000,0000,0000,,从左到右 Dialogue: 0,0:40:49.67,0:40:52.47,Default,,0000,0000,0000,,这不是因为使用了一些旧的器件 Dialogue: 0,0:40:52.66,0:40:57.01,Default,,0000,0000,0000,,他们完全重新实现了这一部分的内容 Dialogue: 0,0:40:57.17,0:40:59.82,Default,,0000,0000,0000,,但是液晶本身就需要以60Hz的速度刷新 Dialogue: 0,0:40:59.99,0:41:01.13,Default,,0000,0000,0000,,所以就这样了 Dialogue: 0,0:41:01.36,0:41:05.94,Default,,0000,0000,0000,,如果要实现一些特效的话是很重要的 Dialogue: 0,0:41:06.15,0:41:06.94,Default,,0000,0000,0000,,比如这个游戏中 Dialogue: 0,0:41:07.11,0:41:09.75,Default,,0000,0000,0000,,屏幕不同的区域行为是不一样的 Dialogue: 0,0:41:09.92,0:41:14.11,Default,,0000,0000,0000,,比如我们先只看这个滚动的城市图 Dialogue: 0,0:41:14.25,0:41:18.54,Default,,0000,0000,0000,,直接全屏滚动肯定是不成问题的 Dialogue: 0,0:41:18.66,0:41:20.46,Default,,0000,0000,0000,,但是我们只想让它在屏幕上的一部分滚动 Dialogue: 0,0:41:20.62,0:41:22.92,Default,,0000,0000,0000,,就可以通过这些额外的寄存器完成 Dialogue: 0,0:41:23.06,0:41:28.47,Default,,0000,0000,0000,,如果你之前接触过8位机的编程 比如C64什么的 那么应该会理解 Dialogue: 0,0:41:28.66,0:41:31.26,Default,,0000,0000,0000,,你可以知道当前正在画哪一行 Dialogue: 0,0:41:31.44,0:41:33.99,Default,,0000,0000,0000,,或者马上会画哪一行 Dialogue: 0,0:41:33.99,0:41:37.38,Default,,0000,0000,0000,,除了一直等着 还可以设定一个中断 Dialogue: 0,0:41:37.60,0:41:39.74,Default,,0000,0000,0000,,一旦到达某一行就会执行特定代码 Dialogue: 0,0:41:39.91,0:41:43.75,Default,,0000,0000,0000,,我们先把SCX寄存器设定到0 Dialogue: 0,0:41:43.90,0:41:45.82,Default,,0000,0000,0000,,然后在第8行触发 Dialogue: 0,0:41:45.98,0:41:48.29,Default,,0000,0000,0000,,所以它就会以卷动为0的参数显示出这些 Dialogue: 0,0:41:48.47,0:41:56.82,Default,,0000,0000,0000,,然后现在我把横向滚动 设置成比如23 然后下一帧设置成24 这样就能滚动了 Dialogue: 0,0:41:57.53,0:42:02.57,Default,,0000,0000,0000,,把对比寄存器设置到42 就会一直继续绘图到42行 Dialogue: 0,0:42:02.74,0:42:09.82,Default,,0000,0000,0000,,设置成其它的 再修改LYC 画完这个路面 一会具体讲路面的事情 Dialogue: 0,0:42:11.24,0:42:14.24,Default,,0000,0000,0000,,最后再设置回0 因为仪表盘不需要卷动 Dialogue: 0,0:42:14.42,0:42:16.69,Default,,0000,0000,0000,,下一帧也是同样这么处理 Dialogue: 0,0:42:16.82,0:42:22.67,Default,,0000,0000,0000,,这个例子中就不需要修改X卷动寄存器了 Dialogue: 0,0:42:22.92,0:42:26.58,Default,,0000,0000,0000,,这个例子中 右上角的马里奥其实是一个窗口 Dialogue: 0,0:42:27.62,0:42:33.45,Default,,0000,0000,0000,,我们在之前讲过 窗口会从左到右从上到下绘图 Dialogue: 0,0:42:33.45,0:42:35.58,Default,,0000,0000,0000,,本身并不能这样只停在右上角 Dialogue: 0,0:42:35.58,0:42:36.51,Default,,0000,0000,0000,,但是可以做到 Dialogue: 0,0:42:37.47,0:42:39.75,Default,,0000,0000,0000,,在第0行触发中断 启用窗口 Dialogue: 0,0:42:39.95,0:42:42.46,Default,,0000,0000,0000,,在第40行的时候再触发中断 关闭窗口 Dialogue: 0,0:42:42.66,0:42:48.66,Default,,0000,0000,0000,,于是在40行的时候 PPU的情况就是:“窗口?啥子窗口?没听过这个说法” Dialogue: 0,0:42:48.84,0:42:50.92,Default,,0000,0000,0000,,于是就不会继续画 Dialogue: 0,0:42:51.09,0:42:53.47,Default,,0000,0000,0000,,这个方法在不同的游戏中都有应用 Dialogue: 0,0:42:53.66,0:42:57.85,Default,,0000,0000,0000,,一些是关于窗口,一些则是和卷动有关 Dialogue: 0,0:42:59.27,0:43:02.45,Default,,0000,0000,0000,,但是如果你不是在一个特定行触发 Dialogue: 0,0:43:02.62,0:43:05.17,Default,,0000,0000,0000,,而是每一行都触发的话 就能实现一些比如这样的效果 Dialogue: 0,0:43:05.37,0:43:06.85,Default,,0000,0000,0000,,左边是屏幕上的效果 Dialogue: 0,0:43:06.85,0:43:11.07,Default,,0000,0000,0000,,右边是实际上存储在显存中的数据 Dialogue: 0,0:43:12.06,0:43:13.97,Default,,0000,0000,0000,,如果你在每一行都改变卷动寄存器 Dialogue: 0,0:43:14.50,0:43:16.89,Default,,0000,0000,0000,,比如按照这个曲线调整 Dialogue: 0,0:43:16.89,0:43:19.14,Default,,0000,0000,0000,,那么就能实现对图像的变形 Dialogue: 0,0:43:19.14,0:43:20.67,Default,,0000,0000,0000,,然后每一帧都改变这个曲线 Dialogue: 0,0:43:20.90,0:43:28.81,Default,,0000,0000,0000,,程序要做的就是 在每一行都向SCX写入一个值 Dialogue: 0,0:43:29.08,0:43:32.83,Default,,0000,0000,0000,,当然如果图片每行都显示那就每行都得修改 Dialogue: 0,0:43:32.100,0:43:37.56,Default,,0000,0000,0000,,而这个赛车游戏的效果其实差不多也是一样的道理 Dialogue: 0,0:43:37.71,0:43:39.29,Default,,0000,0000,0000,,这是视频内存中的情况 Dialogue: 0,0:43:39.50,0:43:40.74,Default,,0000,0000,0000,,只是一条直的路 Dialogue: 0,0:43:40.93,0:43:44.65,Default,,0000,0000,0000,,但是在绘图的时候被扭曲 Dialogue: 0,0:43:44.86,0:43:46.16,Default,,0000,0000,0000,,放大这块 Dialogue: 0,0:43:46.16,0:43:48.46,Default,,0000,0000,0000,,这是原始数据 这是效果 Dialogue: 0,0:43:48.60,0:43:50.92,Default,,0000,0000,0000,,忽略这里的精灵 Dialogue: 0,0:43:51.08,0:43:53.83,Default,,0000,0000,0000,,这是为了扭曲需要的曲线 Dialogue: 0,0:43:53.98,0:43:56.100,Default,,0000,0000,0000,,这是需要的偏移 也就是SCX Dialogue: 0,0:43:56.100,0:44:00.90,Default,,0000,0000,0000,,如果你每行都调整SCX 就能扭曲成这样 Dialogue: 0,0:44:00.99,0:44:02.52,Default,,0000,0000,0000,,另外一件事情就是 Dialogue: 0,0:44:02.65,0:44:08.30,Default,,0000,0000,0000,,路中间的线变成了虚线 路外部也有一些横线的图案 Dialogue: 0,0:44:08.44,0:44:11.68,Default,,0000,0000,0000,,这是通过每几行就调整调色板来实现的 Dialogue: 0,0:44:14.32,0:44:19.14,Default,,0000,0000,0000,,如果看这个游戏的话 甚至可以实现弹跳的效果 Dialogue: 0,0:44:19.28,0:44:24.04,Default,,0000,0000,0000,,这是通过在每行同时调整纵向和横向卷动寄存器实现的 Dialogue: 0,0:44:24.21,0:44:28.27,Default,,0000,0000,0000,,所以就可以重复一行的内容或者跳过某些行 Dialogue: 0,0:44:28.46,0:44:30.81,Default,,0000,0000,0000,,只要计算好 就可以实现这种效果 Dialogue: 0,0:44:30.100,0:44:36.02,Default,,0000,0000,0000,,只要在行中修改垂直卷动寄存器 Dialogue: 0,0:44:36.20,0:44:38.52,Default,,0000,0000,0000,,就能实现二维的扭曲效果 Dialogue: 0,0:44:38.74,0:44:43.52,Default,,0000,0000,0000,,但是我们还得再仔细讲一讲 横向计时 Dialogue: 0,0:44:46.71,0:44:49.01,Default,,0000,0000,0000,,在一行绘制的时候 发生了什么 Dialogue: 0,0:44:49.98,0:44:53.12,Default,,0000,0000,0000,,这是PPU的像素传输模式 Dialogue: 0,0:44:53.30,0:44:55.17,Default,,0000,0000,0000,,通常需要43个时钟的时间 Dialogue: 0,0:44:55.40,0:44:57.82,Default,,0000,0000,0000,,一共144行 Dialogue: 0,0:44:58.04,0:45:00.58,Default,,0000,0000,0000,,但是你不能直接认为 Dialogue: 0,0:45:00.79,0:45:04.96,Default,,0000,0000,0000,,在第一行结束后 它会立即绘制下一行的第一个像素 Dialogue: 0,0:45:05.10,0:45:06.58,Default,,0000,0000,0000,,现实不是这样的 Dialogue: 0,0:45:06.76,0:45:10.91,Default,,0000,0000,0000,,因为在每一行的开始还有一个OAM搜索阶段 需要20时钟 Dialogue: 0,0:45:11.12,0:45:12.28,Default,,0000,0000,0000,,我一会讲 Dialogue: 0,0:45:12.42,0:45:16.37,Default,,0000,0000,0000,,每行的结尾还有一个51时钟的行消隐 Dialogue: 0,0:45:16.64,0:45:19.53,Default,,0000,0000,0000,,在行消隐阶段,PPU就闲着,什么事情都不做。 Dialogue: 0,0:45:19.72,0:45:23.64,Default,,0000,0000,0000,,还有一个场消隐阶段 就是在帧之间的空闲 Dialogue: 0,0:45:23.83,0:45:25.40,Default,,0000,0000,0000,,来计算一下 Dialogue: 0,0:45:25.60,0:45:28.98,Default,,0000,0000,0000,,一行有114时钟 频率是1MHz Dialogue: 0,0:45:29.02,0:45:32.62,Default,,0000,0000,0000,,154行 所以需要这么多个时钟周期完成1帧 Dialogue: 0,0:45:32.62,0:45:35.16,Default,,0000,0000,0000,,如果以用基准频率除以这个 Dialogue: 0,0:45:35.34,0:45:37.76,Default,,0000,0000,0000,,得到的就是59.7Hz的刷新率 Dialogue: 0,0:45:41.49,0:45:45.17,Default,,0000,0000,0000,,PPU当前所在的状态是可以直接读出的 Dialogue: 0,0:45:45.33,0:45:49.35,Default,,0000,0000,0000,,CPU可以知道 而且也可以基于这个设定中断 Dialogue: 0,0:45:49.35,0:45:51.84,Default,,0000,0000,0000,,但是CPU为什么需要知道呢 Dialogue: 0,0:45:52.49,0:45:55.11,Default,,0000,0000,0000,,我们来看看不同模式下都发生了什么 Dialogue: 0,0:45:55.31,0:45:58.61,Default,,0000,0000,0000,,首先 每行开始20周期的OAM搜索是做什么的 Dialogue: 0,0:45:58.78,0:46:04.11,Default,,0000,0000,0000,,每一行 PPU都需要确定这一行中哪些精灵是可见的 Dialogue: 0,0:46:04.11,0:46:06.32,Default,,0000,0000,0000,,所以系统内一共有40个精灵 Dialogue: 0,0:46:06.53,0:46:12.42,Default,,0000,0000,0000,,然后它得找出 这一行中可见的精灵 Dialogue: 0,0:46:12.55,0:46:16.32,Default,,0000,0000,0000,,然后放进一个最多可以保存10个精灵的 可见精灵数组 Dialogue: 0,0:46:16.54,0:46:21.15,Default,,0000,0000,0000,,逻辑是 x坐标不能为0 因为那样就不可见了 Dialogue: 0,0:46:21.34,0:46:27.22,Default,,0000,0000,0000,,然后当前所绘制的行必须要在精灵的第一行和最后一行之间 Dialogue: 0,0:46:27.40,0:46:29.32,Default,,0000,0000,0000,,符合要求就加入可见精灵数组 Dialogue: 0,0:46:29.52,0:46:32.01,Default,,0000,0000,0000,,然后这需要20周期的时间 Dialogue: 0,0:46:32.27,0:46:35.53,Default,,0000,0000,0000,,顺便在原版的GameBoy中这里有个有趣的bug Dialogue: 0,0:46:35.72,0:46:43.99,Default,,0000,0000,0000,,如果你在OAM搜索期间 进行了任何数字在FE00到FEFF之间的16位运算 Dialogue: 0,0:46:44.18,0:46:45.51,Default,,0000,0000,0000,,也就是到OAM内存的指针 Dialogue: 0,0:46:45.65,0:46:47.11,Default,,0000,0000,0000,,即使你没有访问内存 Dialogue: 0,0:46:47.94,0:46:52.02,Default,,0000,0000,0000,,他也会破坏这一块的内存 Dialogue: 0,0:46:56.04,0:46:58.59,Default,,0000,0000,0000,,还有什么需要注意的 Dialogue: 0,0:46:59.89,0:47:01.66,Default,,0000,0000,0000,,CPU连接到内存 Dialogue: 0,0:47:01.91,0:47:04.23,Default,,0000,0000,0000,,PPU连接到显存 Dialogue: 0,0:47:04.44,0:47:07.57,Default,,0000,0000,0000,,OAM内存是特殊的 PPU也直接连接到OAM内存 Dialogue: 0,0:47:07.73,0:47:12.39,Default,,0000,0000,0000,,CPU也可以连接到显存 这样就能写入到显存 Dialogue: 0,0:47:12.39,0:47:13.92,Default,,0000,0000,0000,,但是并不是这样完成的 Dialogue: 0,0:47:14.11,0:47:15.96,Default,,0000,0000,0000,,那样需要双倍速的显存 Dialogue: 0,0:47:16.13,0:47:20.13,Default,,0000,0000,0000,,你看C64是那样做的 但是在GameBoy上就必须经过PPU Dialogue: 0,0:47:20.54,0:47:23.31,Default,,0000,0000,0000,,PPU内部有个开关 PPU可以决定CPU能不能访问 Dialogue: 0,0:47:23.31,0:47:24.84,Default,,0000,0000,0000,,如果PPU不让CPU访问 Dialogue: 0,0:47:24.84,0:47:27.60,Default,,0000,0000,0000,,那么CPU进行写入 什么都不会发生 Dialogue: 0,0:47:27.60,0:47:29.16,Default,,0000,0000,0000,,CPU进行读取 读到的全部是FF Dialogue: 0,0:47:29.27,0:47:31.00,Default,,0000,0000,0000,,至少不会发生什么严重的问题 Dialogue: 0,0:47:31.00,0:47:32.29,Default,,0000,0000,0000,,但是也没有什么意义 Dialogue: 0,0:47:32.29,0:47:36.79,Default,,0000,0000,0000,,所以说CPU必须确保PPU在合适的模式下 这样才能顺利访问 Dialogue: 0,0:47:38.34,0:47:41.60,Default,,0000,0000,0000,,在像素传输阶段 不能访问显存 Dialogue: 0,0:47:41.83,0:47:48.17,Default,,0000,0000,0000,,但是在OAM搜索 行消隐和场消隐阶段都是可以访问的 Dialogue: 0,0:47:48.35,0:47:50.41,Default,,0000,0000,0000,,如果你想要访问OAM内存 Dialogue: 0,0:47:50.64,0:47:54.28,Default,,0000,0000,0000,,OAM搜索或者像素传输都不可以 Dialogue: 0,0:47:54.39,0:47:57.10,Default,,0000,0000,0000,,像素传输时PPU要绘图 需要精灵数据 Dialogue: 0,0:47:57.28,0:47:59.66,Default,,0000,0000,0000,,只能在这些时候才能访问 Dialogue: 0,0:47:59.82,0:48:02.78,Default,,0000,0000,0000,,所以在屏幕绘图时就得十分小心 Dialogue: 0,0:48:03.82,0:48:06.88,Default,,0000,0000,0000,,所以这些时间对于CPU来说都是不好的 Dialogue: 0,0:48:07.08,0:48:08.78,Default,,0000,0000,0000,,不应该做任何重要的事情 Dialogue: 0,0:48:08.97,0:48:12.01,Default,,0000,0000,0000,,比如说CPU想要把新的一行移动进背景映射 Dialogue: 0,0:48:12.01,0:48:13.57,Default,,0000,0000,0000,,最好是在场消隐阶段完成 Dialogue: 0,0:48:13.75,0:48:16.02,Default,,0000,0000,0000,,有最多的不被打断的时间 Dialogue: 0,0:48:16.51,0:48:21.35,Default,,0000,0000,0000,,而所有的游戏逻辑和AI可以在屏幕绘图的时候完成 Dialogue: 0,0:48:21.49,0:48:26.74,Default,,0000,0000,0000,,但是这个时候不能立即写入新的精灵位置 Dialogue: 0,0:48:26.78,0:48:28.18,Default,,0000,0000,0000,,因为OAM也是不能访问的 Dialogue: 0,0:48:28.83,0:48:30.79,Default,,0000,0000,0000,,所以游戏一般的做法都是 Dialogue: 0,0:48:30.99,0:48:36.31,Default,,0000,0000,0000,,把新的精灵信息全部写入一个OAM内存的副本 Dialogue: 0,0:48:36.38,0:48:39.78,Default,,0000,0000,0000,,然后在场消隐阶段复制进OAM Dialogue: 0,0:48:40.04,0:48:44.04,Default,,0000,0000,0000,,就是从任何这里其中一个 存放OAM副本的地方 Dialogue: 0,0:48:44.04,0:48:47.29,Default,,0000,0000,0000,,复制进OAM 这个图不是按比例画的 Dialogue: 0,0:48:48.73,0:48:50.85,Default,,0000,0000,0000,,而且这个过程不需要自己完成 Dialogue: 0,0:48:50.85,0:48:52.57,Default,,0000,0000,0000,,有一个DMA功能 Dialogue: 0,0:48:52.71,0:48:55.53,Default,,0000,0000,0000,,写入想要复制的块 Dialogue: 0,0:48:55.74,0:48:58.63,Default,,0000,0000,0000,,然后等待160个时钟 Dialogue: 0,0:48:58.82,0:49:02.55,Default,,0000,0000,0000,,在复制的过程中 CPU还是在运行的 Dialogue: 0,0:49:02.76,0:49:06.99,Default,,0000,0000,0000,,但是不能访问任何的源地址空间 Dialogue: 0,0:49:07.16,0:49:08.20,Default,,0000,0000,0000,,所以只能等着 Dialogue: 0,0:49:08.39,0:49:11.26,Default,,0000,0000,0000,,但是因为这个代码也得有地方存放 Dialogue: 0,0:49:11.43,0:49:14.11,Default,,0000,0000,0000,,所以可能的地方只有是HRAM Dialogue: 0,0:49:14.32,0:49:15.54,Default,,0000,0000,0000,,也算是个不错的用途 Dialogue: 0,0:49:17.24,0:49:18.95,Default,,0000,0000,0000,,然后是像素流水线 Dialogue: 0,0:49:19.12,0:49:21.94,Default,,0000,0000,0000,,我们继续深入来研究像素流水线 Dialogue: 0,0:49:21.94,0:49:28.66,Default,,0000,0000,0000,,这个还算是非常新的研究 之前是没有公开的 Dialogue: 0,0:49:28.92,0:49:35.03,Default,,0000,0000,0000,,像素FIFO(先入先出缓存)是GameBoy绘图的核心概念 Dialogue: 0,0:49:35.58,0:49:37.21,Default,,0000,0000,0000,,我们直接跳到中间过程 Dialogue: 0,0:49:37.21,0:49:38.64,Default,,0000,0000,0000,,屏幕上已经有一些像素了 Dialogue: 0,0:49:38.64,0:49:42.30,Default,,0000,0000,0000,,比如这5个像素已经被送给LCD了 Dialogue: 0,0:49:42.81,0:49:45.48,Default,,0000,0000,0000,,然后像素FIFO 里面有一些像素 Dialogue: 0,0:49:45.64,0:49:49.96,Default,,0000,0000,0000,,然后每一个4MHz的步骤 它都会移出一个像素 Dialogue: 0,0:49:50.15,0:49:51.46,Default,,0000,0000,0000,,送给LCD Dialogue: 0,0:49:51.70,0:49:53.79,Default,,0000,0000,0000,,移出一个像素 送给LCD Dialogue: 0,0:49:54.05,0:49:55.86,Default,,0000,0000,0000,,然后再移出下一个给LCD Dialogue: 0,0:49:55.86,0:49:59.28,Default,,0000,0000,0000,,你可能注意到那个绿色的指示灯变成红色了 Dialogue: 0,0:49:59.69,0:50:04.15,Default,,0000,0000,0000,,因为像素FIFO必须要有至少8个像素才能移出像素 Dialogue: 0,0:50:04.36,0:50:05.78,Default,,0000,0000,0000,,为什么 一会会讲到 Dialogue: 0,0:50:05.93,0:50:09.39,Default,,0000,0000,0000,,现在需要产生新的数据来填充FIFO了 Dialogue: 0,0:50:09.58,0:50:12.68,Default,,0000,0000,0000,,Fetch(获取)单元就是做这个的 Dialogue: 0,0:50:12.88,0:50:14.56,Default,,0000,0000,0000,,它会读取背景方块单元 Dialogue: 0,0:50:14.73,0:50:18.64,Default,,0000,0000,0000,,9802是目前在读取的映射位置 Dialogue: 0,0:50:18.84,0:50:22.06,Default,,0000,0000,0000,,它从背景映射中读取方块的ID 需要1个周期 Dialogue: 0,0:50:22.22,0:50:28.03,Default,,0000,0000,0000,,然后从方块数据内存 读取第一部分和第二部分的数据 Dialogue: 0,0:50:28.23,0:50:31.62,Default,,0000,0000,0000,,因为每一行的方块是16位 Dialogue: 0,0:50:31.80,0:50:34.77,Default,,0000,0000,0000,,这样它就能产生8个新的像素 Dialogue: 0,0:50:34.94,0:50:38.78,Default,,0000,0000,0000,,然后就重新开始 进入下一个位置 Dialogue: 0,0:50:38.95,0:50:42.88,Default,,0000,0000,0000,,就可以把这8个像素移入FIFO的上半部分 Dialogue: 0,0:50:43.06,0:50:45.67,Default,,0000,0000,0000,,这样就可以继续移出新的像素 Dialogue: 0,0:50:45.85,0:50:47.54,Default,,0000,0000,0000,,然而在执行过程中 Dialogue: 0,0:50:47.76,0:50:51.44,Default,,0000,0000,0000,,并不是说等待有空了 然后开始Fetch填充 移出再这样 Dialogue: 0,0:50:51.44,0:50:54.00,Default,,0000,0000,0000,,并不是交替进行的 而是同时进行的 Dialogue: 0,0:50:55.52,0:50:58.04,Default,,0000,0000,0000,,FIFO是2倍速的 Dialogue: 0,0:50:58.22,0:51:02.10,Default,,0000,0000,0000,,所以Fetch进行1个步骤 FIFO移出两个像素 Dialogue: 0,0:51:02.26,0:51:06.62,Default,,0000,0000,0000,,移出 移出 读取第一字节的数据 Dialogue: 0,0:51:06.80,0:51:10.70,Default,,0000,0000,0000,,移出 移出 读取第二字节的数据 Dialogue: 0,0:51:10.85,0:51:12.41,Default,,0000,0000,0000,,然后到这个时候 Dialogue: 0,0:51:13.39,0:51:16.31,Default,,0000,0000,0000,,现在还不能把数据存入FIFO Dialogue: 0,0:51:16.43,0:51:17.84,Default,,0000,0000,0000,,因为FIFO还放不下 Dialogue: 0,0:51:17.94,0:51:19.92,Default,,0000,0000,0000,,所以Fetch先关闭 Dialogue: 0,0:51:20.04,0:51:21.88,Default,,0000,0000,0000,,等待2个周期 Dialogue: 0,0:51:23.09,0:51:24.80,Default,,0000,0000,0000,,也就是空闲一段时间 Dialogue: 0,0:51:24.95,0:51:26.52,Default,,0000,0000,0000,,然后放入数据 Dialogue: 0,0:51:26.64,0:51:28.91,Default,,0000,0000,0000,,所以如果你看内存访问的模式 Dialogue: 0,0:51:29.06,0:51:33.29,Default,,0000,0000,0000,,就能看见3次读取 1次空闲 3次读取 1次空闲这样 Dialogue: 0,0:51:35.28,0:51:38.94,Default,,0000,0000,0000,,所以 FIFO就是4MHz时钟下 每个周期移出一个像素 Dialogue: 0,0:51:39.08,0:51:40.98,Default,,0000,0000,0000,,除非含有超过8个像素 否则暂停 Dialogue: 0,0:51:40.98,0:51:42.50,Default,,0000,0000,0000,,Fetch单元 运行频率是2MHz Dialogue: 0,0:51:42.50,0:51:44.54,Default,,0000,0000,0000,,需要3个周期来获取8个像素 Dialogue: 0,0:51:44.83,0:51:48.33,Default,,0000,0000,0000,,然后在第四周期停住 直到FIFO有空位 Dialogue: 0,0:51:49.05,0:51:51.16,Default,,0000,0000,0000,,横向移动的实现方法非常简单 Dialogue: 0,0:51:51.31,0:51:52.86,Default,,0000,0000,0000,,比如说我们移动3个像素 Dialogue: 0,0:51:53.00,0:51:54.78,Default,,0000,0000,0000,,所以所有东西都向左移动了3个像素 Dialogue: 0,0:51:54.93,0:51:57.40,Default,,0000,0000,0000,,最先的3个像素就直接无视掉了 Dialogue: 0,0:51:57.53,0:52:00.24,Default,,0000,0000,0000,,然后下一个像素送往LCD Dialogue: 0,0:52:00.38,0:52:01.57,Default,,0000,0000,0000,,而在行的最后 Dialogue: 0,0:52:01.57,0:52:02.82,Default,,0000,0000,0000,,事情变得有趣了 Dialogue: 0,0:52:02.94,0:52:05.81,Default,,0000,0000,0000,,因为我们想在X=160的时候触发 Dialogue: 0,0:52:05.90,0:52:09.06,Default,,0000,0000,0000,,FIFO可能还包含一些根本不会被画出来的像素 Dialogue: 0,0:52:09.15,0:52:14.22,Default,,0000,0000,0000,,然后Fetch可能也已经在获取下8个像素的内容了 也不要了 Dialogue: 0,0:52:14.35,0:52:16.88,Default,,0000,0000,0000,,然后就全部停止 Dialogue: 0,0:52:16.88,0:52:19.22,Default,,0000,0000,0000,,就是干了太多活了 直接进入行消隐 Dialogue: 0,0:52:19.22,0:52:25.43,Default,,0000,0000,0000,,这也是一行需要43周期 而不是40周期的原因 Dialogue: 0,0:52:26.60,0:52:27.78,Default,,0000,0000,0000,,如果我们开启了窗口 Dialogue: 0,0:52:27.89,0:52:30.69,Default,,0000,0000,0000,,比如说窗口坐标是26 Dialogue: 0,0:52:30.82,0:52:34.45,Default,,0000,0000,0000,,我们现在就在26 然后FIFO已经缓存了一些像素了 Dialogue: 0,0:52:34.56,0:52:36.87,Default,,0000,0000,0000,,它会完全清空FIFO Dialogue: 0,0:52:37.04,0:52:38.16,Default,,0000,0000,0000,,然后FIFO会被停止 Dialogue: 0,0:52:38.16,0:52:39.71,Default,,0000,0000,0000,,因为这些像素已经不需要了 Dialogue: 0,0:52:41.44,0:52:44.93,Default,,0000,0000,0000,,然后Fetch会被转到窗口映射 Dialogue: 0,0:52:45.09,0:52:46.96,Default,,0000,0000,0000,,然后Fetch被重新开始 Dialogue: 0,0:52:46.96,0:52:49.61,Default,,0000,0000,0000,,然后还是一样 读ID 读两个字节 Dialogue: 0,0:52:49.61,0:52:51.44,Default,,0000,0000,0000,,就得到了窗口的数据 Dialogue: 0,0:52:51.60,0:52:52.99,Default,,0000,0000,0000,,然后就可以放入像素FIFO Dialogue: 0,0:52:53.10,0:52:56.56,Default,,0000,0000,0000,,只要这些开始被移出了 窗口就绘制出来了 Dialogue: 0,0:52:56.66,0:52:59.56,Default,,0000,0000,0000,,而精灵则是有10个比较器 Dialogue: 0,0:52:59.72,0:53:01.91,Default,,0000,0000,0000,,也是根据X位置触发 Dialogue: 0,0:53:02.05,0:53:05.12,Default,,0000,0000,0000,,比如说在这里X=26有一个精灵 Dialogue: 0,0:53:05.26,0:53:09.86,Default,,0000,0000,0000,,一样 像素FIFO里面有很多像素 然后Fetch执行到一半 Dialogue: 0,0:53:09.99,0:53:12.53,Default,,0000,0000,0000,,首先我们暂时暂停像素FIFO Dialogue: 0,0:53:12.72,0:53:14.33,Default,,0000,0000,0000,,就不能继续移出新的像素 Dialogue: 0,0:53:15.18,0:53:18.39,Default,,0000,0000,0000,,然后暂时调整Fetch让它产生精灵数据 Dialogue: 0,0:53:18.48,0:53:20.61,Default,,0000,0000,0000,,重新开始Fetch Dialogue: 0,0:53:20.74,0:53:22.14,Default,,0000,0000,0000,,然后就得到了精灵数据 Dialogue: 0,0:53:22.32,0:53:24.55,Default,,0000,0000,0000,,然而这次不是放到最后 Dialogue: 0,0:53:24.67,0:53:26.83,Default,,0000,0000,0000,,而是和前8个像素叠加 Dialogue: 0,0:53:26.99,0:53:28.80,Default,,0000,0000,0000,,混合到已有的像素上 Dialogue: 0,0:53:28.96,0:53:32.18,Default,,0000,0000,0000,,这也就解释了为什么FIFO中必须要有至少8个像素 Dialogue: 0,0:53:32.34,0:53:35.05,Default,,0000,0000,0000,,因为精灵是用这种方法来混合的 Dialogue: 0,0:53:36.67,0:53:41.37,Default,,0000,0000,0000,,然后和其它的系统有一个区别 Dialogue: 0,0:53:41.56,0:53:43.92,Default,,0000,0000,0000,,在窗口开始前 都以恒定速度移出像素 Dialogue: 0,0:53:44.10,0:53:46.09,Default,,0000,0000,0000,,当窗口开始的时候 Dialogue: 0,0:53:46.20,0:53:51.49,Default,,0000,0000,0000,,FIFO被清空 很长一段时间都不能输出数据 Dialogue: 0,0:53:51.60,0:53:54.33,Default,,0000,0000,0000,,直到FIFO内有了窗口数据 Dialogue: 0,0:53:54.42,0:53:57.48,Default,,0000,0000,0000,,也就是等到恢复了 Dialogue: 0,0:53:57.61,0:53:59.89,Default,,0000,0000,0000,,也就是需要至少43个周期 Dialogue: 0,0:54:00.06,0:54:03.54,Default,,0000,0000,0000,,如果有精灵就需要更多 Dialogue: 0,0:54:03.70,0:54:06.48,Default,,0000,0000,0000,,在基于液晶的系统上这么做是完全可行的 Dialogue: 0,0:54:06.48,0:54:07.80,Default,,0000,0000,0000,,你可以暂停发送像素 Dialogue: 0,0:54:07.93,0:54:09.66,Default,,0000,0000,0000,,而在基于CRT的系统上 不行 Dialogue: 0,0:54:09.92,0:54:11.52,Default,,0000,0000,0000,,比如说在C64上 Dialogue: 0,0:54:11.68,0:54:14.18,Default,,0000,0000,0000,,一行必须是正好的40时钟 Dialogue: 0,0:54:14.26,0:54:18.66,Default,,0000,0000,0000,,因为任何晚出来的像素看起来都会被右移 Dialogue: 0,0:54:20.83,0:54:23.47,Default,,0000,0000,0000,,所以这个图并不是完全准确 Dialogue: 0,0:54:23.54,0:54:26.54,Default,,0000,0000,0000,,像素传输应该是至少43时钟 Dialogue: 0,0:54:26.66,0:54:30.45,Default,,0000,0000,0000,,行消隐则是剩下的时间 Dialogue: 0,0:54:30.69,0:54:34.55,Default,,0000,0000,0000,,然后实际过程中 取决于屏幕上的内容 更接近于这样 Dialogue: 0,0:54:37.48,0:54:41.08,Default,,0000,0000,0000,,但是之前这个并不是像素FIFO真正的工作方式 Dialogue: 0,0:54:41.08,0:54:43.30,Default,,0000,0000,0000,,它并不存储像素颜色 Dialogue: 0,0:54:43.30,0:54:49.01,Default,,0000,0000,0000,,它存储的是原始的位组合 Dialogue: 0,0:54:49.17,0:54:50.15,Default,,0000,0000,0000,,以及来源 Dialogue: 0,0:54:50.34,0:54:53.34,Default,,0000,0000,0000,,比如说这里是9个背景像素 Dialogue: 0,0:54:53.52,0:54:55.02,Default,,0000,0000,0000,,Fetch也是一样的 Dialogue: 0,0:54:55.15,0:54:56.80,Default,,0000,0000,0000,,它并不产生像素颜色 Dialogue: 0,0:54:56.97,0:55:00.01,Default,,0000,0000,0000,,它产生的是位组合 Dialogue: 0,0:55:00.21,0:55:04.94,Default,,0000,0000,0000,,加上来源或者精灵调色板 Dialogue: 0,0:55:05.10,0:55:07.39,Default,,0000,0000,0000,,我们来把这个混合一下 Dialogue: 0,0:55:07.59,0:55:10.49,Default,,0000,0000,0000,,精灵的00表示在背景之上绘图 Dialogue: 0,0:55:10.70,0:55:12.42,Default,,0000,0000,0000,,来过一遍 Dialogue: 0,0:55:12.61,0:55:16.75,Default,,0000,0000,0000,,这里是精灵调色板1 数据00 表明是透明的 背景获胜 Dialogue: 0,0:55:16.82,0:55:20.36,Default,,0000,0000,0000,,这个情况下精灵获胜 因为应该画在背景之上 Dialogue: 0,0:55:20.46,0:55:22.70,Default,,0000,0000,0000,,大部分像素都是这个情况 Dialogue: 0,0:55:22.85,0:55:30.49,Default,,0000,0000,0000,,而最后这个像素 是精灵调色板1 数据透明 所以背景获胜 Dialogue: 0,0:55:30.67,0:55:33.99,Default,,0000,0000,0000,,再来和同一坐标下另外一个精灵混合一下 Dialogue: 0,0:55:36.85,0:55:42.18,Default,,0000,0000,0000,,这里是精灵调色板0 在背景之上 精灵获胜 Dialogue: 0,0:55:42.34,0:55:45.59,Default,,0000,0000,0000,,然后这个情况下 新的精灵不会覆盖旧的 Dialogue: 0,0:55:45.75,0:55:50.26,Default,,0000,0000,0000,,所以旧的获胜 然后就一直这样 Dialogue: 0,0:55:50.39,0:55:52.71,Default,,0000,0000,0000,,这也就是精灵会画在右边精灵的上面 Dialogue: 0,0:55:52.71,0:55:54.71,Default,,0000,0000,0000,,但是不会画在已有精灵之上 Dialogue: 0,0:55:54.86,0:55:57.93,Default,,0000,0000,0000,,高ID精灵输给低ID精灵的原因 Dialogue: 0,0:55:58.10,0:56:00.43,Default,,0000,0000,0000,,最后这里新的精灵又获胜了 Dialogue: 0,0:56:00.59,0:56:03.67,Default,,0000,0000,0000,,然后应用上调色板 Dialogue: 0,0:56:03.77,0:56:06.08,Default,,0000,0000,0000,,只有在最后像素被移出的时候才进行 Dialogue: 0,0:56:06.20,0:56:09.14,Default,,0000,0000,0000,,这里对应调色板 移出一个像素到液晶 Dialogue: 0,0:56:09.29,0:56:14.02,Default,,0000,0000,0000,,查表 转换 LCD Dialogue: 0,0:56:14.49,0:56:16.73,Default,,0000,0000,0000,,另外一个 黑色 Dialogue: 0,0:56:17.93,0:56:22.05,Default,,0000,0000,0000,,这也是在彩色机型上的做法 Dialogue: 0,0:56:22.21,0:56:24.28,Default,,0000,0000,0000,,从SGB开始 Dialogue: 0,0:56:24.45,0:56:27.23,Default,,0000,0000,0000,,现有的游戏不能处理颜色 但是可以上色 Dialogue: 0,0:56:27.37,0:56:32.58,Default,,0000,0000,0000,,然后就是 已有的三种调色板现在变成了RGB调色板 Dialogue: 0,0:56:32.69,0:56:34.34,Default,,0000,0000,0000,,其它所有的都是一致的 Dialogue: 0,0:56:35.84,0:56:38.73,Default,,0000,0000,0000,,但是一旦移出像素 Dialogue: 0,0:56:38.88,0:56:41.62,Default,,0000,0000,0000,,它就对应RGB颜色 Dialogue: 0,0:56:41.84,0:56:43.27,Default,,0000,0000,0000,,把这个粉色的像素显示在屏幕上 Dialogue: 0,0:56:43.52,0:56:46.19,Default,,0000,0000,0000,,S1 11是这里 Dialogue: 0,0:56:46.37,0:56:48.64,Default,,0000,0000,0000,,黑色像素 Dialogue: 0,0:56:48.79,0:56:53.69,Default,,0000,0000,0000,,再来一个例子 S1 01 精灵调色板1 显示在屏幕上 Dialogue: 0,0:56:54.67,0:56:56.70,Default,,0000,0000,0000,,所有技术性内容到此为止 Dialogue: 0,0:57:08.83,0:57:09.58,Default,,0000,0000,0000,,还有5分钟的时间 Dialogue: 0,0:57:12.03,0:57:13.22,Default,,0000,0000,0000,,来讲讲开发 Dialogue: 0,0:57:13.54,0:57:16.20,Default,,0000,0000,0000,,如果你对GameBoy开发感兴趣 Dialogue: 0,0:57:16.34,0:57:17.87,Default,,0000,0000,0000,,有一些很不错的开发工具 Dialogue: 0,0:57:18.02,0:57:21.79,Default,,0000,0000,0000,,Rednex Game Boy 开发系统是一套命令行工具 Dialogue: 0,0:57:21.96,0:57:24.62,Default,,0000,0000,0000,,可以配合自己的编辑器和Makefile使用 Dialogue: 0,0:57:24.80,0:57:27.05,Default,,0000,0000,0000,,如果想要Debug Dialogue: 0,0:57:27.21,0:57:30.11,Default,,0000,0000,0000,,BGB模拟器 就很不错 Dialogue: 0,0:57:30.11,0:57:35.45,Default,,0000,0000,0000,,为Windows设计 但是配合Wine在OSX和Linux上也没问题 Dialogue: 0,0:57:35.72,0:57:38.52,Default,,0000,0000,0000,,内置调试器 断点啊 单步啊 一类的 Dialogue: 0,0:57:38.52,0:57:43.27,Default,,0000,0000,0000,,然后还有一个显存查看器 可以查看所有发生的事情 Dialogue: 0,0:57:43.36,0:57:47.28,Default,,0000,0000,0000,,很适合在上面运行Demo然后观察发生了什么 Dialogue: 0,0:57:48.29,0:57:50.79,Default,,0000,0000,0000,,如果你想要在真机上运行 Dialogue: 0,0:57:50.79,0:57:52.90,Default,,0000,0000,0000,,也有像Everdrive一类的设备 Dialogue: 0,0:57:53.03,0:57:54.50,Default,,0000,0000,0000,,可以插SD卡 Dialogue: 0,0:57:56.18,0:57:58.69,Default,,0000,0000,0000,,因为还有4分钟时间 Dialogue: 0,0:57:58.84,0:58:02.86,Default,,0000,0000,0000,,我们来谈谈我最喜欢的GameBoy外设 Dialogue: 0,0:58:02.86,0:58:04.17,Default,,0000,0000,0000,,Game Boy Camera Dialogue: 0,0:58:04.34,0:58:05.90,Default,,0000,0000,0000,,但是不是技术层面 Dialogue: 0,0:58:06.01,0:58:07.93,Default,,0000,0000,0000,,只是吹一波这个设备 Dialogue: 0,0:58:08.10,0:58:09.30,Default,,0000,0000,0000,,这个就是Game Boy Camera Dialogue: 0,0:58:09.47,0:58:11.71,Default,,0000,0000,0000,,你把它插入GameBoy Dialogue: 0,0:58:11.84,0:58:13.61,Default,,0000,0000,0000,,能拍照片 Dialogue: 0,0:58:13.70,0:58:15.15,Default,,0000,0000,0000,,然后可以用Game Boy Printer打印出来 Dialogue: 0,0:58:15.30,0:58:17.14,Default,,0000,0000,0000,,用的热敏纸 Dialogue: 0,0:58:17.27,0:58:18.83,Default,,0000,0000,0000,,如果还买得到的话 Dialogue: 0,0:58:20.23,0:58:23.91,Default,,0000,0000,0000,,然后可以拍出像这样的照片 Dialogue: 0,0:58:24.08,0:58:25.96,Default,,0000,0000,0000,,放大一点 Dialogue: 0,0:58:30.60,0:58:31.99,Default,,0000,0000,0000,,非常棒的照片 Dialogue: 0,0:58:33.06,0:58:37.60,Default,,0000,0000,0000,,每张照片 都是用这个14K像素的CCD拍出来的 Dialogue: 0,0:58:38.66,0:58:42.14,Default,,0000,0000,0000,,位深2位 (译者注:硬件为3位,抖动为2位以匹配GameBoy屏幕) Dialogue: 0,0:58:52.58,0:58:55.97,Default,,0000,0000,0000,,所以下次去旅游的时候 记得带上GameBoy Dialogue: 0,0:59:09.49,0:59:15.96,Default,,0000,0000,0000,,然后还有Game Boy Camera 加上一台带并口的PC 还有已经买不到的联机线 Dialogue: 0,0:59:16.09,0:59:24.31,Default,,0000,0000,0000,,所以感谢这些人 研究GameBoy 以及帮助我准备这场讲座 Dialogue: 0,0:59:24.83,0:59:27.71,Default,,0000,0000,0000,,这些人也是以各种途径帮助了我 Dialogue: 0,0:59:29.60,0:59:30.54,Default,,0000,0000,0000,,所以 Dialogue: 0,0:59:40.08,0:59:43.51,Default,,0000,0000,0000,,在这个系列中 这已经是第五场讲座 Dialogue: 0,0:59:43.67,0:59:44.80,Default,,0000,0000,0000,,下一个是什么 Dialogue: 0,0:59:45.06,0:59:48.30,Default,,0000,0000,0000,,明年应该有个讲座吧 Dialogue: 0,0:59:48.49,0:59:51.21,Default,,0000,0000,0000,,我建议两个讲座 Dialogue: 0,0:59:51.29,0:59:54.30,Default,,0000,0000,0000,,我就先给34C3几个提名 Dialogue: 0,0:59:55.26,0:59:58.91,Default,,0000,0000,0000,,Dominik Wagner来讲Acorn Archimedes Dialogue: 0,1:00:03.86,1:00:16.08,Default,,0000,0000,0000,,然后Jannis Harder来讲SNES Dialogue: 0,1:00:16.38,1:00:18.81,Default,,0000,0000,0000,,这是你们自己的选择 可以做这些讲座 Dialogue: 0,1:00:18.97,1:00:21.52,Default,,0000,0000,0000,,或者也可以在自己头上倒冰水 Dialogue: 0,1:00:25.77,1:00:27.14,Default,,0000,0000,0000,,感谢参加 明年见 Dialogue: 0,1:00:28.57,1:01:07.00,Default,,0000,0000,0000,,subtitles created by c3subtitles.de\Nin the year 2017. Join, and help us!