PageSourceSearch

https://pcsx2.net/assets/js/9ac49be4.c71d8a80.js

js pcsx2.net collected 2026-10-02 03:48:04 UTC 7,213 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkpcsx_2_net=self.webpackChunkpcsx_2_net||[]).push([["12180"],{69220:function(e,t,n){n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var s=n(92206),i=n(85893),a=n(50065);let o={authors:["jake stine"],date:new Date("2009-06-02T00:00:00.000Z"),description:"One of the less obvious things that has plagued PCSX2's compatibility over the years is its event handling system",draft:!1,tags:["devblog"],title:"Events Plenty"},l=void 0,r={authorsImageUrls:[void 0]},c=[];function h(e){let t={em:"em",li:"li",p:"p",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"One of the less obvious things that has plagued Pcsx2's compatibility\nover the years is its event handling system. The system in place as of\n0.9.6 is adequate for interpreter-based emulation but is not\nwell-equipped to handle the methods that a recompiler uses to manage cpu\ncycle updates. This is something we aim to fix in the coming weeks."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Cycle-based Timing Explained"})}),"\n",(0,i.jsxs)(t.p,{children:["All cpus have a cycle rate, which is typically the Mhz/Ghz values you're\nmost familiar with when talking about any cpu. An i7 clocked at 2.83ghz\nhas a 2.83ghz cycle rate. Now, the actual throughput of instructions can\nvary greatly since each cycle of the cpu consists of several ",(0,i.jsx)(t.em,{children:"stages"}),"\nand multiple piplines, each of which can have dependency stalls and has\nvarying rules for when such stalls occur. The cycle rate, however, is\nalways 2.83ghz. Because cycle rates are a known constant, they make a\ngood barometer for synchronizing the activities of a multi-processor\ndesign like the Playstation 2."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Why do Recompilers Complicate Event Testing?"})}),"\n",(0,i.jsx)(t.p,{children:"Recompilers work as a significant speedup over interpreters by doing two\nthings:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Recompile the machine code of a emulated CPU (in our case MIPS\ninstructions) into code native to the host machine (ix86\ninstructions)."}),"\n",(0,i.jsx)(t.li,{children:"Prefetch and pre-decode emulated instructions, and inline them into\nblocks."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["The thing recompilers are most well-known for -- recompiling to native\nmachine code -- is actually the less effective of the two things\nrecompilers do for speeding up emulation. The primary speedup typically\ncomes from the prefetching and inlining of instructions, which in\naddition to eliminating the instruction fetch/decode stage (by far the\nslowest part of any interpreter), also allows for cross-instruction\noptimizations such as constant propagation and register caching/mapping.\nIn other words, a recompiler is effectively executing emulated\ninstructions in pre-compiled ",(0,i.jsx)(t.em,{children:"bursts"})," . This is so important to\nperformance that a recompiler without block-level execution would hardly\nbe any faster than an interpreter."]}),"\n",(0,i.jsx)(t.p,{children:"As part of the design of block-level execution, the recompiled code only\nupdates cpu cycle c
1ounts and tests for scheduled events at block\nboundaries. Blocks typically span 5 to 35 cycles, but in some cases can\nspan a hundred cycles or more. When the subsequent Event Test is\nperformed, several scheduled events may be pending execution. This is\nwhere problems can occur: The current event system implemented into\nPcsx2 executes all pending events in no particular order, leading to\nevents being executed out-of-order when multiple events time-out during\na single block. Typically most events don't have dependencies on each\nother, or games don't use them in a way that execution order matters.\nBut sometimes they do, and in those cases behavior can be unpredictable,\nor can cause the game to fail outright. To make matters worse, the\npending events typically don't know how late they are, and will\nre-schedule subsequent events in increasingly belated fashion. The\ncurrent implementation of EE and IOP counters have tons of complicated\ncode meant to compensate for this limitation (both slow and were nearly\nimpossible to get right)."}),"\n",(0,i.jsxs)(t.p,{children:["The fix for this is to use an event system I'll call ",(0,i.jsx)(t.strong,{children:"decremental delta\ntime."})," It has three advantages:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Makes it easy to execute events in scheduled order regardless of the\namount of time which has passed since the last Event Test."}),"\n",(0,i.jsx)(t.li,{children:'Maintains relative cycle scheduling at a high level so that none of\nthe events being re-scheduled "lose time" due to belated\nblock-boundary event testing.'}),"\n",(0,i.jsx)(t.li,{children:"Simplifies event handling on all levels, and provides significant\nspeedups for event testing and event dispatching."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"It's hard to know beforehand just how beneficial in-order execution of\nevents will be. I'm anticipating that it might actually fix a few\nemulation problems on the IOP recompiler in particular, since it has a\nslow cycle rate and also has a handful of events which can have\npotential inter-dependencies. For that reason I'll be implementing the\nsystem first into the IOP, and then when all the chinks in its armor are\nworked free we'll port the EE side of the emulator over to it."})]})}function d(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},50065:function(e,t,n){n.d(t,{Z:()=>l,a:()=>o});var s=n(67294);let i={},a=s.createContext(i);function o(e){let t=s.useContext(a);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(a.Provider,{value:t},e.children)}},92206:function(e){e.exports=JSON.parse('{"permalink":"/blog/2009/events-plenty","editUrl":"https://github.com/PCSX2/pcsx2-net-www/tree/main/blog/2009/events-plenty/index.mdx","source":"@site/blog/2009/events-plenty/index.mdx","title":"Events Plenty","description":"One of the less obvious things that has plagued PCSX2\'s compatibility over the years is its event handling system","date":"2009-06-02T00:00:00.000Z","tags":[{"inline":true,"label":"devblog","permalink":"/blog/tags/devblog"}],"readingTime":3.43,"hasTruncateMarker":true,"authors":[{"name":"Jake Stine","key":"jake stine","page":null}],"frontMatter":{"authors":["jake stine"],"date":"2009-06-02T00:00:00.000Z","description":"One of the less obvious things that has plagued PCSX2\'s compatibility over the years is its event handling system","draft":false,"tags":["devblog"],"title":"Events Plenty"},"unlisted":false,"prevItem":{"title":"Recompilers All Dems Buzzwords","permalink":"/blog/2009/recompilers-all-dems-buzzwords"},"nextItem":{"title":"PCSX2 Logo Design Contest","permalink":"/blog/2009/pcsx2-logo-design-contest"}}')}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.