中断

  • 中断和中断处理程序
    • 中断的硬件实现
    • CPU中断处理流程图
    • GameBoy 中的中断
  • 实现:中断标志
  • 实现:中断处理
  • 下一次:更大的游戏

在上一部分中,通过引入精灵,为模拟游戏奠定了基础。但是,仿真器缺少一个方面:垂直消隐中断。这部分会从整体上介绍中断,特别是实现消隐中断;完成此操作后,模拟器将运行俄罗斯方块。

想象一下,您有一台带有网卡的计算机,以及一些处理来自网络的数据的软件。从计算机的角度来看,数据只是每隔一段时间就会进来,因此您需要某种方式让软件知道新数据已经到达。有两种方法可以实现:

轮询:软件每隔一段时间询问网卡是否有新数据到达。这是一种简单的做事方式,但有缺点:

  • 软件在定期检查之前不知道新数据,这意味着数据到达计算机与软件处理之间存在延迟;
  • 必须定期抽出时间进行检查,即使没有数据到达,也要从其他工作中抽出时间;
  • 如果轮询进程每次检查都处理一个新数据,但数据到达速度更快,则网卡中会产生数据积压,并且有可能丢失某些数据;
  • 如果没有其他工作要做,软件仍然要检查数据,这使计算机保持全速运行而无需做任何工作。

中断:网卡通知软件有新数据到达。这是一种更复杂的数据接收方式,涉及的步骤更多,但它减轻了轮询的所有缺点:

  • 新数据一到就可以处理,到达和处理数据之间没有延迟;
  • 当确实有数据要处理时,软件只需要花时间处理数据,并且可以根据需要随时调用处理例程以清除任何积压;
  • 如果没有其他工作要做,计算机可以进入低功耗模式,直到网卡唤醒它以获取新数据。

中断和中断处理程序

中断的硬件实现

很明显,中断的概念是一个有用的概念,但是中断的工作同时有硬件和软件要求。在硬件方面,当中断到达时,CPU 必须暂时停止执行它正在执行的操作,而是开始执行中断处理程序(有时称为中断服务程序)。在上述场景中,网卡和 CPU 之间运行了一条线,允许网卡在数据到达时通知 CPU。

CPU中断处理流程图

CPU 将在每条指令结束时检查其中断输入。如果某个附加的外围设备(如网卡)发出了中断信号,则 CPU 将采取步骤启动中断处理程序:CPU 将保存它停止正常执行的位置,注册中断发生的事实,以及跳转到处理程序。

GameBoy 中的中断

在 GameBoy 中,有五种不同的中断线,从各种外设馈入。每个都有自己的 ISR,位于内存中的不同地址;中断列表如下。

打断 ISR 地址(十六进制)
垂直空白 0040
LCD 状态触发 0048
定时器溢出 0050
串行链接 0058
手柄按键 0060

在垂直空白的情况下,在LCD底部穿入一根电线;一旦 GPU 完成对所有 LCD 线的扫描并运行到屏幕底部,中断就会触发并且 CPU 跳转到0040,执行消隐 ISR。

实现:中断标志

大多数 CPU 包含用于中断的“主标志”:如果启用此标志,它们将仅由 CPU 处理。GameBoy 中的 Z80 也不例外,但还有一些额外的寄存器可以处理 GameBoy 中可用的各个中断。这些是内存寄存器,因此它们由内存管理单元处理:

MMU 中的中断标志

登记 地点 笔记 细节
中断
使能
FFFF 当位被设置时,可以触发
相应的
中断
少量 当 0 当 1
0 空白关闭 空白
1 液晶显示器关闭 液晶显示
2 定时器关闭 打开定时器
3 串行关闭 连续上
4 手柄关闭 手柄开启
中断
标志
FF0F 当位被设置时,发生
了中断
位的
顺序与FFFF

由于这些是内存寄存器,因此它们的实现是针对 MMU 的:

MMU.js:中断标志

MMU = {_ie: 0,_if: 0,rb: function(addr){switch(addr & 0xF000){...case 0xF000:switch(addr & 0x0F00){...// Zero-pagecase 0xF00:if(addr == 0xFFFF){return MMU._ie;}else if(addr >= 0xFF80){return MMU._zram[addr & 0x7F];}else{// I/O control handlingswitch(addr & 0x00F0){case 0x00:if(addr == 0xFF0F) return MMU._if;break;...}return 0;}}}},...
};

Z80 的“主启用”开关以类似的方式用于 Z80 实现。CPU 为软件提供操作码以将主使能切换到开或关位置,因此还需要实现这些:

Z80.js:中断主使能

Z80 = {_r: {ime: 0,...},reset: function(){...Z80._r.ime = 1;},// Disable IMEDI: function(){Z80._r.ime = 0;Z80._r.m = 1;Z80._r.t = 4;},// Enable IMEEI: function(){Z80._r.ime = 1;Z80._r.m = 1;Z80._r.t = 4;}
};

实现:中断处理

中断标志就位后,可以重新开发主执行循环,使其更符合 CPU中断处理流程图 中的执行路径。执行后,需要检查中断标志以查看是否发生了启用的中断;如果有,则可以调用其处理程序。

Z80.js:Vblank 中断处理程序

Z80 = {_ops: {...// Start vblank handler (0040h)RST40: function(){// Disable further interruptsZ80._r.ime = 0;// Save current SP on the stackZ80._r.sp -= 2;MMU.ww(Z80._r.sp, Z80._r.pc);// Jump to handlerZ80._r.pc = 0x0040;Z80._r.m = 3;Z80._r.t = 12;},// Return from interrupt (called by handler)RETI: function(){// Restore interruptsZ80._r.ime = 1;// Jump to the address on the stackZ80._r.pc = MMU.rw(Z80._r.sp);Z80._r.sp += 2;Z80._r.m = 3;Z80._r.t = 12;}}
};while(true)
{// Run execute for this instructionvar op = MMU.rc(Z80._r.pc++);Z80._map[op]();Z80._r.pc &= 65535;Z80._clock.m += Z80._r.m;Z80._clock.t += Z80._r.t;Z80._r.m = 0;Z80._r.t = 0;// If IME is on, and some interrupts are enabled in IE, and// an interrupt flag is set, handle the interruptif(Z80._r.ime && MMU._ie && MMU._if){// Mask off ints that aren't enabledvar ifired = MMU._ie & MMU._if;if(ifired & 0x01){MMU._if &= (255 - 0x01);Z80._ops.RST40();}}Z80._clock.m += Z80._r.m;Z80._clock.t += Z80._r.t;
}

下一次:更大的游戏

模拟器已经达到了一个合理的阶段:它至少能够以某种形式模拟已发布的游戏。但是,它确实存在游戏大小的问题。俄罗斯方块是一个 32kB ROM,完全适合内存映射中的“ROM”空间。游戏往往具有比这更大的 ROM,并且卡带遵循将 ROM 的一部分映射到内存的过程。下一次,我将研究 GameBoy 最简单的可用 ROM 映射形式,以及它在 64kB 游戏 ROM 上的实现。

Game boy模拟器(8):中断相关推荐

  1. appium+Python+逍遥游模拟器自动化执行测试用例,为什么一直中断连接?

    appium++逍遥游模拟器自动化执行测试用例,为什么一直中断连接? 问题:模拟器不稳定,断开连接 电脑配置:还不错,所以不是这个问题 解决方法:以管理员方式运行appium和逍遥游模拟器,成功解决问 ...

  2. 10 51单片机汇编:让定时器产生中断(使用Keil模拟器)[系列教程之10]

    10 51单片机汇编:让定时器产生中断(使用Keil模拟器)[系列教程之10] 该系列主仓库地址:https://gitee.com/langcai1943/8051-from-boot-to-app ...

  3. Android模拟器学framework和driver之传感器篇1(linux sensor driver)

    对于android模拟器开发环境的搭建这里我就不多说了,网上google下一大堆,还有就是android 模拟器的kernel使用的是goldfish的kernel,可以使用git得到源码,然后就可以 ...

  4. NES模拟器开发-CPU笔记

    我的项目XNES已经开始动手编码了,目前的进度大概是cpu的模拟完成了大概10~20%左右.简单记录一下CPU模拟过程中遇到的问题和思考. 原理: cpu模拟实际就是模拟cpu处理opcode的过程, ...

  5. Windows Phone 模拟器(Emulator) 加载程序一闪而过就自动退出的解决办法

    今天在做一个Windows Phone 程序.在一番重构之后突然发现按F5调试程序时,模拟器可以启动,并且加载了程序,不过只是闪了一下,然后程序迅速退出了.没有任何出错信息,也没有任何log文件.在程 ...

  6. 交换机模拟配置软件_网络设备模拟器Packet Tracer实验

    实验一 网络连接线的制作 首先,我们将学习如何制作直通线和交叉线,并用做线连通性测试仪测试线路是否可以正常工作.然后,再学习如何利用做好的缆线将两台工作站连接起来. 工具 / 准备: (1) Cat5 ...

  7. 利用任务调度特性检测Android模拟器

    Author:leonnewton 0x00 前言 DEXLabs发表过题为<Detecting Android Sandboxes>的博客,文章提出了一个检测Android沙箱的方法,并 ...

  8. WindowsPhone-GameBoy模拟器开发四--Gameboy显示系统分析

    这次说一下GB的显示系统,先从一幅Gb的内存分布图说起,请看图: 图中红色框框起来的部分就是这篇文章关注的部分,这一部分的内存地址从8000-9Fff,共8KB,这一部分是从来存储背景和游戏" ...

  9. linux串口中断_5年匠心之作,深度探索Linux虚拟化

    01为什么写这本书 大约在2014年底,我参与了一个项目,使用Android模拟器在x86架构的机器上运行各种Android游戏.当时项目遇到的核心问题是游戏运行卡顿严重,印象中普通的小游戏每秒大约只 ...

最新文章

  1. eclipse更新time out的问题
  2. GPRS管理与创建APN拨号连接
  3. 【java】修改包访问的数据
  4. CLion IDE 来调试 JVM 源码
  5. c#类的定义,c#中的关健字,C#标识符
  6. .net 导出excel_.NET Core一行代码导入导出Excel生成Word
  7. Apache HTTP Server与Tomcat 的三种连接方式介绍
  8. 【交通标志识别】基于matlab GUI SIFT交通标志识别【含Matlab源码 864期】
  9. 软件项目管理知识点总结
  10. 理解 GBK、Unicode、utf-8
  11. 数字电子技术基础——第二章 逻辑代数基础
  12. 论文作业(1):VOIP 中Speex/ILBCISAC/SILK比较
  13. C#与Halcon联合编程之如何使Halcon窗口显示的图片适应窗口控件的大小
  14. 用tig来查看git log
  15. 找单生狗,模拟atoi,模拟offsetof,交换奇偶位
  16. 使用微软官方工具下载安装Windows10系统
  17. ppt文件如何压缩到最小?
  18. 互联网利用短信网关收发短信
  19. SPI总线的特点、工作方式及常见错误解答重点是SCK时钟频率时间
  20. 安装Tomcat详细步骤

热门文章

  1. day1学习vue2笔记 vue指令
  2. 2021-07-09 支付行业发展特点与所面临的挑战需求
  3. 当遇到网站打不开,你会怎么排查它的问题?
  4. html中注册商标r怎么打,如何在PPT里打一个圈加一个R,就是已经注册的标志?
  5. python有什么好玩的书_史上最全的Python书排行榜|你想知道的都在这里
  6. 年轻程序员与老程序员的对话
  7. 北京科技大学 计算机考研真题,北京科技大学计算机系统结构和组成原理考研真题...
  8. 【Get深一度】关于dB,那些你需要知道的常识
  9. 集古今异宝 供八方收藏
  10. NB-IoT天线同轴电缆RG316、RG174、RG178