47 changed files with 15217 additions and 0 deletions
-
796Docs/Chapter 1.1 Setting up Graphics and Hello World.htm
-
474Docs/Chapter 1.1 Setting up Graphics and Hello World_files/analytics.js
-
500Docs/Chapter 1.1 Setting up Graphics and Hello World_files/banner-styles.css
-
147Docs/Chapter 1.1 Setting up Graphics and Hello World_files/bufferlayout.svg
-
3Docs/Chapter 1.1 Setting up Graphics and Hello World_files/bundle-playback.js
-
286Docs/Chapter 1.1 Setting up Graphics and Hello World_files/gpudiagram.svg
-
116Docs/Chapter 1.1 Setting up Graphics and Hello World_files/iconochive.css
-
70Docs/Chapter 1.1 Setting up Graphics and Hello World_files/style.css
-
261Docs/Chapter 1.1 Setting up Graphics and Hello World_files/vram-layout.svg
-
21Docs/Chapter 1.1 Setting up Graphics and Hello World_files/wombat.js
-
413Docs/Chapter 1.2 Drawing Graphics.htm
-
474Docs/Chapter 1.2 Drawing Graphics_files/analytics.js
-
500Docs/Chapter 1.2 Drawing Graphics_files/banner-styles.css
-
3Docs/Chapter 1.2 Drawing Graphics_files/bundle-playback.js
-
116Docs/Chapter 1.2 Drawing Graphics_files/iconochive.css
-
876Docs/Chapter 1.2 Drawing Graphics_files/ordertable-buffercompare.svg
-
705Docs/Chapter 1.2 Drawing Graphics_files/ordertable-multiprims.svg
-
657Docs/Chapter 1.2 Drawing Graphics_files/ordertable-primitive.svg
-
633Docs/Chapter 1.2 Drawing Graphics_files/ordertable.svg
-
350Docs/Chapter 1.2 Drawing Graphics_files/primstruct.svg
-
70Docs/Chapter 1.2 Drawing Graphics_files/style.css
-
21Docs/Chapter 1.2 Drawing Graphics_files/wombat.js
-
919Docs/Chapter 1.3 Textures, TPages and CLUTs.htm
-
705Docs/Chapter 1.3 Textures, TPages and CLUTs_files/ordertable-multiprims.svg
-
268Docs/Chapter 1.3 Textures, TPages and CLUTs_files/page-texcoord-relation.svg
-
49Docs/Chapter 1.3 Textures, TPages and CLUTs_files/style.css
-
313Docs/Chapter 1.3 Textures, TPages and CLUTs_files/vram-texture-coordinates.svg
-
192Docs/Chapter 1.3 Textures, TPages and CLUTs_files/vram-texture-pages.svg
-
672Docs/Chapter 1.4 Controllers.htm
-
474Docs/Chapter 1.4 Controllers_files/analytics.js
-
500Docs/Chapter 1.4 Controllers_files/banner-styles.css
-
3Docs/Chapter 1.4 Controllers_files/bundle-playback.js
-
116Docs/Chapter 1.4 Controllers_files/iconochive.css
-
70Docs/Chapter 1.4 Controllers_files/style.css
-
21Docs/Chapter 1.4 Controllers_files/wombat.js
-
826Docs/Chapter 1.5 Fixed point Math.htm
-
49Docs/Chapter 1.5 Fixed point Math_files/style.css
-
807Docs/Chapter 1.6 Using the CD-ROM.htm
-
49Docs/Chapter 1.6 Using the CD-ROM_files/style.css
-
508Docs/Chapter 2.2 Reading a file from CD-ROM.htm
-
474Docs/Chapter 2.2 Reading a file from CD-ROM_files/analytics.js
-
500Docs/Chapter 2.2 Reading a file from CD-ROM_files/banner-styles.css
-
3Docs/Chapter 2.2 Reading a file from CD-ROM_files/bundle-playback.js
-
116Docs/Chapter 2.2 Reading a file from CD-ROM_files/iconochive.css
-
70Docs/Chapter 2.2 Reading a file from CD-ROM_files/style.css
-
21Docs/Chapter 2.2 Reading a file from CD-ROM_files/wombat.js
-
BINDocs/LibPSn00b Reference.pdf
@ -0,0 +1,796 @@ |
|||
<html><head><script src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/analytics.js" type="text/javascript"></script> |
|||
<script type="text/javascript">window.addEventListener('DOMContentLoaded',function(){var v=archive_analytics.values;v.service='wb';v.server_name='wwwb-app211.us.archive.org';v.server_ms=363;archive_analytics.send_pageview({});});</script> |
|||
<script type="text/javascript" src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/bundle-playback.js" charset="utf-8"></script> |
|||
<script type="text/javascript" src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/wombat.js" charset="utf-8"></script> |
|||
<script type="text/javascript"> |
|||
__wm.init("http://web.archive.org/web"); |
|||
__wm.wombat("http://lameguy64.net/tutorials/pstutorials/chapter1/1-display.html","20220827033533","http://web.archive.org/","web","/_static/", |
|||
"1661571333"); |
|||
</script> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/banner-styles.css"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/iconochive.css"> |
|||
<!-- End Wayback Rewrite JS Include --> |
|||
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/style.css"> |
|||
<title>Chapter 1.1: Setting up Graphics and Hello World</title><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></head> |
|||
|
|||
|
|||
<body><!-- BEGIN WAYBACK TOOLBAR INSERT --> |
|||
<style type="text/css"> |
|||
body { |
|||
margin-top:0 !important; |
|||
padding-top:0 !important; |
|||
/*min-width:800px !important;*/ |
|||
} |
|||
</style> |
|||
<script>__wm.rw(0);</script> |
|||
<div id="wm-ipp-base" style="display: block; direction: ltr; height: 1px;" lang="en"> |
|||
</div><div id="wm-ipp-print">The Wayback Machine - |
|||
http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter1/1-display.html</div> |
|||
<script type="text/javascript">//<![CDATA[ |
|||
__wm.bt(675,27,25,2,"web","http://lameguy64.net/tutorials/pstutorials/chapter1/1-display.html","20220827033533",1996,"/_static/",["/_static/css/banner-styles.css?v=fantwOh2","/_static/css/iconochive.css?v=qtvMKcIJ"], false); |
|||
__wm.rw(1); |
|||
//]]></script> |
|||
<!-- END WAYBACK TOOLBAR INSERT --> |
|||
|
|||
|
|||
<h1>1.1. Setting up Graphics and Hello World</h1> |
|||
<p> |
|||
This chapter teaches the basics of initializing and setting up the GPU of the |
|||
PSX. Areas covered in this chapter include the GPU, VRAM and the concept of |
|||
display and drawing environments which are essential for better understanding |
|||
how the GPU works when programming for the PSX. |
|||
</p> |
|||
<p> |
|||
This tutorial series does not and will not cover graphics programming using the |
|||
LIBGS library which is a high level graphics library that adds about 100KB |
|||
worth of overhead to your project (remember that the PSX only has 2MB of RAM) |
|||
and hides many of the inner workings of the GPU, making it difficult to |
|||
understand how to use the GPU directly and would often get in the way when |
|||
trying to write your own graphics routines... While it may sound elitist |
|||
discouraging the use of LIBGS as it provides facilities for rendering 3D models |
|||
easily, it is better to learn how to work with LIBGPU (or PSXGPU in PSn00bSDK) |
|||
in the long term as the knowledge gained from learning how to use it directly |
|||
will become very important in the future for either better performance, or to |
|||
accomplish special graphical effects. |
|||
</p> |
|||
<p><b>Tutorial compatible with PSn00bSDK:</b>Yes</p> |
|||
|
|||
<h2>Chapter Index</h2> |
|||
<ul> |
|||
<li><a href="#whystart">Why Start with Graphics?</a></li> |
|||
<li><a href="#gpusummary">Brief Summary of the GPU</a></li> |
|||
<li><a href="#hellostart">Writing the Hello World Program</a></li> |
|||
<li><a href="#gpusetup">Setting up Graphics</a></li> |
|||
<li><a href="#hellodisplay">Displaying the Hello World</a></li> |
|||
<li><a href="#samplecode">Final Sample Code</a></li> |
|||
<li><a href="#result">Result</a></li> |
|||
<li><a href="#conclusion">Conclusion</a></li> |
|||
</ul> |
|||
|
|||
|
|||
<h2 id="whystart">Why Start with Graphics?</h2> |
|||
<p> |
|||
This tutorial series begins with graphics programming as displaying a hello |
|||
world message requires a bit of graphics programming, as neither the official |
|||
SDK or PSn00bSDK provide a framebuffer text console for displaying text largely |
|||
due to the way how the hardware works. But both provide a means of basic text |
|||
drawing functions intended for debugging purposes which will be demonstrated |
|||
for this chapter. |
|||
</p> |
|||
<p> |
|||
Besides, most of the satisfaction gained when learning to develop for a new |
|||
platform comes from seeing the result displayed on the television screen by the |
|||
console you're learning to develop for and you're going need to learn graphics |
|||
programming anyway to really be able to do anything interesting with the PSX. |
|||
It is a <b>video</b> game console afterall. |
|||
</p> |
|||
|
|||
|
|||
<h2 id="gpusummary">Brief Summary of the GPU</h2> |
|||
<p> |
|||
The GPU, as the name suggests, is the graphics processor responsible for doing |
|||
the graphics rendering work for both 2D and 3D visuals. The block diagram shown |
|||
below illustrates the relevant components that make up the entirerity of the |
|||
PSX's graphics subsystem, including the MDEC and GTE hardware responsible for |
|||
video playback and 3D graphics capabilities respectively. |
|||
</p> |
|||
<img src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/gpudiagram.svg"> |
|||
<ul> |
|||
<li>1MB of VRAM with 16-bit data bus.</li> |
|||
<li>2KB of texture cache.</li> |
|||
<li>Supports non-interlaced, low resolution and interlaced, high resolution |
|||
video modes.</li> |
|||
<li>16-bit color rendering with optional dithering.</li> |
|||
<li>Draws rectangles, sprites, lines, polylines, flat, shaded and texture |
|||
mapped polygon primitives.</li> |
|||
<li>Estimated 300,000 flat and gouraud shaded polygons per second.</li> |
|||
<li>Estimated 150,000 texture mapped polygons per second.</li> |
|||
</ul> |
|||
|
|||
<h3>The GPU is not 3D</h3> |
|||
<p> |
|||
A worrying amount often believed that the PSX's GPU is capable of rendering 3D |
|||
polygons. While it may seem to be the case to the uneducated, the GPU is in |
|||
fact only capable of drawing primitives in 2D space. Therefore, the GPU is |
|||
incapable of perspective correct texture mapping which results in affine |
|||
texture distortion and the occasional buggy near clipping seen in a lot of 3D |
|||
PSX games. It was common for games to minimize the distortion by subdividing |
|||
large polygons into smaller polygons with perspective correct subdivision. |
|||
</p> |
|||
<p> |
|||
The bulk of the 3D processing is instead done on the CPU which features a |
|||
co-processor suited for such tasks known as the GTE or Geometry Transform |
|||
Engine. The GTE is effectively an all integer math co-processor that provides |
|||
matrix multiplication, vector transformations and projection operations at high |
|||
speed which the CPU alone couldn't do at reasonable speed. Software would then |
|||
assemble primitive packets using results from the GTE which are then sent to |
|||
the GPU as a linked list via high speed DMA transfer for the GPU to draw said |
|||
primitives. |
|||
</p> |
|||
<p> |
|||
The GTE will not be covered in this chapter as it is not required for simple |
|||
2D graphics programming. Whilst in the topic of the GTE, a very important |
|||
issue must be taken care of and that is the GTE is <b>NOT</b> a Geometry |
|||
<i>Transfer</i> Engine. An equally concerning amount belive that the GTE |
|||
stands for Geometry Transfer Engine and not a Transform Engine when in fact, |
|||
the GTE only does math calculations and is not capable of doing any |
|||
<i>"transfer"</i> operations whatsoever. Also, the GTE can only be accessed |
|||
by the CPU through standard co-processor related instructions. Just wanted to |
|||
clarify this before going any further in learning how to program for the PSX |
|||
as this bothers me to no end. Suppose it can be used to identify if one is a |
|||
real PSX programmer or not. |
|||
</p> |
|||
|
|||
<h3>Only 16-bit Color Rendering</h3> |
|||
<p> |
|||
Some often mistake that the PSX renders graphics in 24-bit color depth. Whilst |
|||
the GPU is capable of 24-bit true color output, it cannot draw primitives in |
|||
24-bit color. So the 24-bit color mode is only really useful for MDEC video |
|||
sequences or static images in 24-bit color. |
|||
</p> |
|||
<p> |
|||
The GPU can only draw at 16-bit color depth in a RGB5I1 pixel format (five bits |
|||
per RGB component plus one mask bit used as a mask for semi-transparency |
|||
effects). This aligns perfectly with the 16-bit data bus of the VRAM. |
|||
</p> |
|||
|
|||
<h3>The VRAM</h3> |
|||
<p> |
|||
The GPU features it's own 1MB of VRAM. If you look back at the block diagram |
|||
shown earlier you'll see that the VRAM is connected to the GPU and is not |
|||
connected the system bus at all. This means the VRAM is not memory mapped and |
|||
the CPU cannot access it directly. Instead, VRAM access can only be done |
|||
through the GPU. Fortunately, transfers are done via high speed DMA. |
|||
</p> |
|||
<p> |
|||
Naturally, the GPU uses the VRAM for storing framebuffers and texture images. |
|||
The most interesting aspect about the VRAM is how the GPU treats it like a |
|||
1024x512 16-bit image, with areas of VRAM addressed by (X,Y) coordinates |
|||
instead of a linear memory address range. Display and drawing framebuffers as |
|||
well as texture images reside as rectangular images in the VRAM. The following |
|||
illustrates a typical VRAM layout for framebuffers and texture images in PSX |
|||
games. |
|||
</p> |
|||
<img src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/vram-layout.svg"> |
|||
|
|||
<h3>Primitive Packets</h3> |
|||
<p> |
|||
The GPU is instructed through the use of primitive packets, which are small |
|||
bits of formatted data that make up a GPU command which are sent to the GPU |
|||
via DMA for drawing. The primitive packets not only specify the type of |
|||
primitive but also the color, semi-transparency flags, (X,Y) coordinates, |
|||
texture coordinates, color look-up table to use and so forth. Think of them |
|||
like arguments for a function call. |
|||
</p> |
|||
<p> |
|||
The number of arguments a primitive packet requires depends on the type of |
|||
primitive. The simplest primitives such as a texture page primitive only takes |
|||
one argument while the most sophisticated primitive; a texture mapped, gouraud |
|||
shaded, 4-point polygon takes as many as 14 arguments. This also means the |
|||
size of the primitive varies, with the texture page primitive being only a |
|||
word in size while a 4-point, texture mapped and gouraud shaded polygon is |
|||
12 words long on top of the tag word present at the start of all primitives. |
|||
</p> |
|||
<p> |
|||
Further details about primitive packets will be covered in a future chapter. |
|||
</p> |
|||
|
|||
<h3>Framebuffers</h3> |
|||
<p> |
|||
Framebuffers for graphics display and drawing reside in VRAM as rectangular |
|||
areas defined in (X,Y) coordinates. The size of the display area is based on |
|||
the video mode (ie. the display area is 320x240 pixels when running in |
|||
320x240 mode). On the other hand, the size for the drawing area can be of any |
|||
arbitrary size which may be used to render texture images for accomplishing |
|||
certain render to texture based visual effects. Normally, the size of the |
|||
drawing area should typically be equal to the display area. |
|||
</p> |
|||
<p> |
|||
The display and drawing areas are defined as an environment using the |
|||
<b>DISPENV</b> and <b>DRAWENV</b> structs. Each struct defines various |
|||
parameters that are relevant to their respective environment. The |
|||
<b>DISPENV</b> and <b>DRAWENV</b> structs are initialized using |
|||
<b>SetDefDispEnv()</b> and <b>SetDefDrawEnv()</b> respectively which defines |
|||
the default parameters for each environment, which may be customized later for |
|||
your project's requirements. Once the environments have been defined they can |
|||
then be applied to the GPU using <b>PutDispEnv()</b> and <b>PutDrawEnv()</b> |
|||
to make each environment effective. |
|||
</p> |
|||
<p> |
|||
Learning the display and drawing environments are mandatory for being able to |
|||
get any graphical output from the PSX and this will be covered extensively in |
|||
this chapter. |
|||
</p> |
|||
|
|||
<h2 id="hellostart">Writing the Hello World Program</h2> |
|||
<p> |
|||
As obligatory as it may sound, a hello world is an effective and simple enough |
|||
example to get started with PSX homebrew programming. A hello world program for |
|||
the PSX can't be a simple call of printf(), unless you only want to see the |
|||
output through a tty which, in all honesty, won't look as interesting as |
|||
showing the message on the TV screen or emulator window. |
|||
</p> |
|||
<p> |
|||
The basic run-down of accomplishing a hello world on the PSX is to perform the |
|||
following operations: |
|||
</p> |
|||
<ul> |
|||
<li>Initialize the GPU.</li> |
|||
<li>Define display and drawing environments.</li> |
|||
<li>Initializing the debug font.</li> |
|||
<li>Display the hello world text.</li> |
|||
</ul> |
|||
<p> |
|||
Break out your preferred text editor and begin writing the hello world program |
|||
as you go along this chapter. |
|||
</p> |
|||
|
|||
<h3>Required Headers</h3> |
|||
<p> |
|||
First, include some necessary headers in your C file. The most important of which is |
|||
libgpu.h as it provides various definitions provided by the libgpu library. libgte.h |
|||
is required even if you don't plan to use the GTE as libgpu.h depends on some |
|||
definitions provided in it. |
|||
</p> |
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <libetc.h> // Includes some functions that controls the display |
|||
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <libgpu.h> // GPU library header |
|||
</pre> |
|||
<p> |
|||
If using PSn00bSDK, replace the <b>lib</b> prefix with <b>psx</b> instead. Most |
|||
of the definitions between the official SDK and PSn00bSDK are identical, so the |
|||
syntax of things shouldn't be much to worry much about. |
|||
</p> |
|||
|
|||
<h3>Write the main() Function</h3> |
|||
<p> |
|||
Like with any C program, you must define a main() function somewhere in your |
|||
project. You can omit the argc and argv definitions if desired as they don't |
|||
work on the PSX. |
|||
</p> |
|||
<pre>int main() |
|||
{ |
|||
return 0; |
|||
} |
|||
</pre> |
|||
<p> |
|||
A return value cannot be passed to a parent executable as the kernel does not |
|||
save the value for the caller to receive it, but is required nonetheless to |
|||
keep the compiler from complaining about returning without a value. |
|||
</p> |
|||
|
|||
|
|||
<h2 id="gpusetup">Setting up Graphics</h2> |
|||
<p> |
|||
The very first thing to do before anything else in your PSX program is to |
|||
call <b>ResetGraph()</b>. <b>ResetGraph()</b> not only resets the GPU as the |
|||
name suggests, but it also enables interrupts which are mandatory for getting |
|||
anything done on the PSX. If <b>ResetGraph()</b> is not called functions that |
|||
depend on interrupts such as <b>VSync()</b> and several other things will not |
|||
work, and will usually appear as though your program just crashed. |
|||
</p> |
|||
<pre>// Reset GPU and enable interrupts |
|||
ResetGraph(0); |
|||
</pre> |
|||
<p> |
|||
Resetting the GPU also masks out the video output which results in a black |
|||
screen, but the console still produces video sync. The video output is enabled |
|||
again using <b>SetDispMask()</b>, ideally after a <b>DISPENV</b> has been |
|||
defined and applied to the GPU for a smooth transition from a previously |
|||
running program (ie. the startup screen). As <b>ResetGraph()</b> does not clear |
|||
the contents of VRAM, so whatever was drawn by the previous program still |
|||
remains when your program takes over. Clearing the VRAM is generally not |
|||
required in most well coded scenarios. |
|||
</p> |
|||
|
|||
<h3>Setting up the DISPENV and DRAWENV Environments</h3> |
|||
<p> |
|||
Start by defining two <b>DISPENV</b> and <b>DRAWENV</b> variables as arrays in |
|||
your code. Define an int which will be used for keeping track of things which |
|||
will make total sense later on. This value must be set to zero as part of your |
|||
graphics initialization code just to make sure the variable starts with a value |
|||
of zero. |
|||
</p> |
|||
<pre>// Define environment pairs and buffer counter |
|||
DISPENV disp[2]; |
|||
DRAWENV draw[2]; |
|||
int db; |
|||
</pre> |
|||
<p> |
|||
Next is to define the <b>DISPENV</b> pair. Initializing the <b>DISPENV</b> |
|||
structure is easiest done using the <b>SetDefDispEnv()</b> function with simple |
|||
arguments. |
|||
</p> |
|||
<b>For NTSC users:</b> |
|||
<pre>// Configures the pair of DISPENVs for 320x240 mode (NTSC) |
|||
SetDefDispEnv(&disp;[0], 0, 0, 320, 240); |
|||
SetDefDispEnv(&disp;[1], 0, 240, 320, 240); |
|||
</pre> |
|||
<b>For PAL users:</b> |
|||
<pre>// Configures the pair of DISPENVs for 320x256 mode (PAL) |
|||
SetDefDispEnv(&disp;[0], 0, 0, 320, 256); |
|||
SetDefDispEnv(&disp;[1], 0, 256, 320, 256); |
|||
|
|||
// Screen offset to center the picture vertically |
|||
disp[0].screen.y = 24; |
|||
disp[1].screen.y = disp[0].screen.y; |
|||
|
|||
// Forces PAL video standard |
|||
SetVideoMode(MODE_PAL); |
|||
</pre> |
|||
<p> |
|||
This defines both <b>DISPENV</b>s for 320x240 resolution mode (320x256 if you |
|||
used the PAL snippet) which is the most commonly used video mode. The first |
|||
<b>DISPENV</b> is set with a position of (0,0) while the second <b>DISPENV</b> |
|||
is set with a VRAM offset of (0,240). You might be wondering why it has to be |
|||
defined that way. |
|||
</p> |
|||
<p> |
|||
Next is to define the <b>DRAWENV</b>s. Much like the <b>DISPENV</b>s you use |
|||
<b>SetDefDrawEnv()</b> to initialize the <b>DRAWENV</b> structure with |
|||
simple arguments. |
|||
</p> |
|||
<b>For NTSC users:</b> |
|||
<pre>// Configures the pair of DRAWENVs for the DISPENVs |
|||
SetDefDrawEnv(&draw;[0], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw;[1], 0, 0, 320, 240); |
|||
</pre> |
|||
<b>For PAL users:</b> |
|||
<pre>// Configures the pair of DRAWENVs for the DISPENVs |
|||
SetDefDrawEnv(&draw;[0], 0, 256, 320, 256); |
|||
SetDefDrawEnv(&draw;[1], 0, 0, 320, 256); |
|||
</pre> |
|||
<p> |
|||
Unlike <b>DISPENV</b>, <b>DRAWENV</b> can be of any arbitrary size for the |
|||
drawing environment. But generally it should be equal to the size of the |
|||
<b>DISPENV</b> defined, so the drawn area will align perfectly with the display |
|||
environments. Additionally, you'll want to set some parameters within the |
|||
<b>DRAWENV</b> struct to enable background clearing as otherwise you'll get a |
|||
hall of mirrors effect. The background clear takes effect as soon as the |
|||
<b>DRAWENV</b> is applied to the GPU using <b>PutDrawEnv()</b>. |
|||
</p> |
|||
<pre>// Specifies the clear color of the DRAWENV |
|||
setRGB0(&draw;[0], 63, 0, 127); |
|||
setRGB0(&draw;[1], 63, 0, 127); |
|||
// Enable background clear |
|||
draw[0].isbg = 1; |
|||
draw[1].isbg = 1; |
|||
</pre> |
|||
<p> |
|||
Finally, apply the <b>DISPENV</b>/<b>DRAWENV</b> environments to the GPU to |
|||
apply the new video mode and drawing environment to achieve a seamless |
|||
transition. |
|||
</p> |
|||
<pre>// Apply environments |
|||
PutDispEnv(&disp;[0]); |
|||
PutDrawEnv(&draw;[0]); |
|||
</pre> |
|||
<p> |
|||
To keep your code look neat and tidy, you'll want to put all the graphics init |
|||
code inside a function, to keep your <b>main()</b> function from looking messy |
|||
and will make expanding the program easier in the future. |
|||
</p> |
|||
|
|||
<h3>The Concept of Double Buffered Rendering</h3> |
|||
<p> |
|||
You may have noticed that the <b>DRAWENV</b> pairs are somewhat positioned in |
|||
the opposite order as the <b>DISPENV</b> whilst writing the graphics init code |
|||
and are probably wondering why this is the case instead of a <b>DRAWENV</b> |
|||
directly overlapping a <b>DISPENV</b>. This is how you implement double |
|||
buffered rendering on the PSX and is a standard feature to have when writing |
|||
real-time graphics code, not just on the PSX but on almost any system with a |
|||
framebuffer. |
|||
</p> |
|||
<p> |
|||
If you're not familiar with the concept, you basically need to allocate two |
|||
framebuffer areas; one for display and one for drawing. The way you use these |
|||
framebuffers is you use one buffer as the display buffer, which is the buffer |
|||
the graphics hardware will display on the screen and the other as the drawing |
|||
buffer, where all your graphics operations should draw to and is not shown on |
|||
the screen. Once drawing is complete the two buffers switch places, the drawing |
|||
buffer becomes the display buffer and the display buffer become the drawing |
|||
buffer for the next frame to be drawn and the cycle repeats. This basically |
|||
guarantees that only completed frames are shown on the screen which yields |
|||
seamless graphical animations even during framerate drops when intensive |
|||
visuals are being drawn aside from the natural reduction of smoothness. |
|||
</p> |
|||
<img src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/bufferlayout.svg"> |
|||
<p> |
|||
Having a <b>DISPENV</b> and a <b>DRAWENV</b> simply overlap one another on the |
|||
same area counts as single buffered rendering and whilst you may get away with |
|||
it, the amount of things you can draw/process will be severely limited as you'll |
|||
get nasty flicker if the drawing/processing does not complete before the v-blank |
|||
period ends. So, a double buffered rendering scheme is much preferred. |
|||
</p> |
|||
|
|||
<h3>The Display Function</h3> |
|||
<p> |
|||
Now the last thing that deals with the <b>DISPENV</b> and <b>DRAWENV</b> |
|||
environments to write is a so called display function, which is basically |
|||
a function that does the all buffer swap stuff in a single call for |
|||
convenience. Calling the display function should be done at the end of your |
|||
loop as that is usually where all graphics operations have completed |
|||
and are ready for drawing or display. For this tutorial, the display function |
|||
will be named <h>display()</h>. |
|||
</p> |
|||
<p> |
|||
Before performing a buffer swap, you must first call <b>DrawSync()</b> then |
|||
<b>VSync()</b>. As the names suggests these functions waits for the GPU to |
|||
complete any drawing operations and waits for the vertical blanking period |
|||
respectively. Waiting for <b>DrawSync()</b> is important as it makes sure that |
|||
the GPU has completed drawing any primitives as otherwise you may get flicker |
|||
or possibly instability. Waiting for <b>VSync()</b> is also important as it |
|||
not only caps your program loop to the TV refresh rate (60fps for NTSC, 50 |
|||
for PAL) but it also prevents screen tearing which will happen if you swap |
|||
buffers without waiting for the v-blank period. |
|||
</p> |
|||
<pre>// Wait for GPU to finish drawing and V-Blank |
|||
DrawSync(0); |
|||
VSync(0); |
|||
</pre> |
|||
<p> |
|||
Now the next step is to perform the buffer swap. If you remember that variable |
|||
named <h>db</h> earlier, this variable will be used as a counter to keep track |
|||
of which buffer pair to switch to. Since there are only two <b>DISPENV</b> and |
|||
<b>DRAWENV</b> pairs this variable will simply alternate between 1 and 0 on |
|||
every call of the display function. This easily achieved using a NOT (!) |
|||
operator. |
|||
</p> |
|||
<pre>// Flip buffer counter |
|||
db = !db; |
|||
</pre> |
|||
<p> |
|||
Then apply the environment pair based on the value of <h>db</h> to the GPU. |
|||
</p> |
|||
<pre>// Apply environments |
|||
PutDispEnv(&disp;[db]); |
|||
PutDrawEnv(&draw;[db]); |
|||
</pre> |
|||
<p> |
|||
And finally, call <b>SetDispMask()</b> to lift the display mask so you get |
|||
picture instead of a black screen, as <b>ResetGraph()</b> masks the display |
|||
by default. |
|||
</p> |
|||
<pre>// Enable display |
|||
SetDispMask(1); |
|||
</pre> |
|||
|
|||
<h3>Verifying the Code</h3> |
|||
<p> |
|||
To make sure you're right on track, here's a listing of what the code should |
|||
look like. |
|||
</p> |
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <libetc.h> // Includes some functions that controls the display |
|||
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <libgpu.h> // GPU library header |
|||
|
|||
// Define environment pairs and buffer counter |
|||
DISPENV disp[2]; |
|||
DRAWENV draw[2]; |
|||
int db; |
|||
|
|||
void init(void) |
|||
{ |
|||
// Reset GPU and enable interrupts |
|||
ResetGraph(0); |
|||
|
|||
// Configures the pair of DISPENVs for 320x240 mode (NTSC) |
|||
SetDefDispEnv(&disp;[0], 0, 0, 320, 240); |
|||
SetDefDispEnv(&disp;[1], 0, 240, 320, 240); |
|||
|
|||
// Configures the pair of DRAWENVs for the DISPENVs |
|||
SetDefDrawEnv(&draw;[0], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw;[1], 0, 0, 320, 240); |
|||
|
|||
// Specifies the clear color of the DRAWENV |
|||
setRGB0(&draw;[0], 63, 0, 127); |
|||
setRGB0(&draw;[1], 63, 0, 127); |
|||
|
|||
// Enable background clear |
|||
draw[0].isbg = 1; |
|||
draw[1].isbg = 1; |
|||
|
|||
// Apply environments |
|||
PutDispEnv(&disp;[0]); |
|||
PutDrawEnv(&draw;[0]); |
|||
|
|||
// Make sure db starts with zero |
|||
db = 0; |
|||
} |
|||
|
|||
void display(void) |
|||
{ |
|||
// Wait for GPU to finish drawing and V-Blank |
|||
DrawSync(0); |
|||
VSync(0); |
|||
|
|||
// Flip buffer counter |
|||
db = !db; |
|||
|
|||
// Apply environments |
|||
PutDispEnv(&disp;[db]); |
|||
PutDrawEnv(&draw;[db]); |
|||
|
|||
// Enable display |
|||
SetDispMask(1); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
// Initialize graphics and stuff |
|||
init(); |
|||
|
|||
// Main loop |
|||
while(1) |
|||
{ |
|||
display(); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
|
|||
<h3>Compiling and Testing</h3> |
|||
<p>Now that you've written a considerable amount of code for the graphics |
|||
init and buffer swapping stuff, it should be possible to compile the code |
|||
and see an output to check if you're right on track. In the official |
|||
PsyQ/Programmers' Tool SDK compiling can be done through <b>ccpsx</b> with |
|||
a single command line. <b>ccpsx</b> is actually a front for the C, C++ and |
|||
linker that makes using the SDK's toolchain easier. |
|||
</p> |
|||
<pre>ccpsx -O2 -Xo0x80010000 hello.c -o hello.cpe |
|||
</pre> |
|||
<p> |
|||
If you've worked with C before, you should already know that <h>-O2</h> |
|||
specifies the optimization level for the compiler generated code just like |
|||
in most other C compilers. The <h>-Xo0x80010000</h> parameter would likely |
|||
be unfamiliar to you and this specifies the target address your executable's |
|||
program text is going to reside when it is being loaded by the console. |
|||
The target address is usually set to 0x80010000 which is the start of user |
|||
space memory on the PSX as the first 64KB is reserved by the kernel. |
|||
</p> |
|||
<p> |
|||
The executables <b>ccpsx</b> produces are in CPE format which cannot be |
|||
booted from the CD by the PSX and most emulators don't support it. You'll |
|||
have to convert the executable into the usable PS-EXE format which can be |
|||
done using <b>cpe2x</b>. |
|||
</p> |
|||
<pre>cpe2x hello.cpe |
|||
</pre> |
|||
<p>Don't be fooled by the .EXE file extension of a PS-EXE executable file. The |
|||
executable files <b>cpe2x</b> produces are neither MS-DOS or Windows |
|||
executable programs. |
|||
</p> |
|||
<p>If using PSn00bSDK. It is more complicated to compile a program from within |
|||
the command line alone due to the way how the toolchain is currently set up. |
|||
It is much easier to just copy a makefile from one of the examples included |
|||
in the SDK and tweak the variables for your project. Then use <b>make</b> |
|||
to compile the program and it should produce an ELF file and a PS-EXE file. |
|||
</p> |
|||
<p>Run the program and you should get a solid blue image. |
|||
</p> |
|||
<img src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/1-display.png"> |
|||
|
|||
|
|||
<h2 id="hellodisplay">Displaying the Hello World</h2> |
|||
<p>Now that the graphics environment and display routines have been implemented, |
|||
the next step is to draw the hello world message. This is easily done by using |
|||
the debug font functions <b>FntLoad()</b>, <b>FntOpen()</b> and |
|||
<b>FntPrint()</b>. These functions are not suited for general use. Such as in |
|||
a game title as it does not support any form of customization and does not |
|||
support lowercase letters, but is good enough for testing and debugging |
|||
purposes which will be useful later. These functions are provided by libetc, |
|||
or psxetc in PSn00bSDK. |
|||
</p> |
|||
|
|||
<h3>Setting up the Debug Font</h3> |
|||
<p>The first thing to do before the debug font functions can be used is to is |
|||
load the font texture onto VRAM using <b>FntLoad()</b>. The font texture can be |
|||
placed anywhere in the VRAM area provided it doesn't get overwritten by |
|||
display/draw areas, or textures being loaded onto VRAM. For this tutorial, the |
|||
font texture will be placed at (960,0). |
|||
</p> |
|||
<p>Next is to create a text stream using <b>FntOpen()</b> which defines the |
|||
area where the text will be drawn at. For this tutorial a text stream of 100 |
|||
characters is defined to fill the entire screen, with some overscan |
|||
compensation to ensure that the text is visible on the TV. |
|||
</p> |
|||
<pre>// Load the internal font texture |
|||
FntLoad(960, 0); |
|||
// Create the text stream |
|||
FntOpen(0, 8, 320, 224, 0, 100); |
|||
</pre> |
|||
<p>The font area coordinates are draw-area relative and not VRAM relative, so |
|||
there is no need to define another font area for each of the display/draw areas |
|||
in the VRAM. The third argument specifies if a black background for the font |
|||
area should be drawn. In PSn00bSDK, you can specify 2 for a semi-transparent |
|||
black background. If you try to set it to a non-zero value, the background will |
|||
turn black because the font area covers the entire screen. |
|||
</p> |
|||
<p><b>FntOpen()</b> allows defining multiple font areas by saving the return |
|||
value to a persistent variable and passing it as the first argument of |
|||
<b>FntPrint()</b> and <b>FntFlush()</b>. Up to eight font areas can be defined |
|||
at once, but it cannot be closed or redefined later in your program. |
|||
</p> |
|||
<h3>Printing and Displaying Hello World</h3> |
|||
<p><b>FntPrint()</b> prints text to the last defined font area and works more |
|||
or less like <b>printf()</b> and you can also use the newline character |
|||
sequence <h>\n</h> to move a line of text down. A font handle can be specified |
|||
as an optional first argument of <b>FntPrint()</b>, but in PSn00bSDK a handle |
|||
from <b>FntOpen()</b> or -1 must be specified as the first argument. This |
|||
</p> |
|||
<pre>FntPrint("HELLO WORLD!"); |
|||
|
|||
FntFlush(-1); |
|||
display(); |
|||
</pre> |
|||
<p>Calling <b>FntPrint()</b> alone is not enough to display text to the |
|||
current draw area, so <b>FntFlush()</b> needs to be called to actually draw |
|||
the characters printed from <b>FntPrint()</b> calls. |
|||
</p> |
|||
|
|||
<h2 id="samplecode">Final Sample Code</h2> |
|||
<p>Compare your code against this listing to make sure you're right on |
|||
track. |
|||
</p> |
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <libetc.h> // Includes some functions that controls the display |
|||
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <libgpu.h> // GPU library header |
|||
|
|||
// Define environment pairs and buffer counter |
|||
DISPENV disp[2]; |
|||
DRAWENV draw[2]; |
|||
int db; |
|||
|
|||
void init(void) |
|||
{ |
|||
// Reset GPU and enable interrupts |
|||
ResetGraph(0); |
|||
|
|||
// Configures the pair of DISPENVs for 320x240 mode (NTSC) |
|||
SetDefDispEnv(&disp;[0], 0, 0, 320, 240); |
|||
SetDefDispEnv(&disp;[1], 0, 240, 320, 240); |
|||
|
|||
// Configures the pair of DRAWENVs for the DISPENVs |
|||
SetDefDrawEnv(&draw;[0], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw;[1], 0, 0, 320, 240); |
|||
|
|||
// Specifies the clear color of the DRAWENV |
|||
setRGB0(&draw;[0], 63, 0, 127); |
|||
setRGB0(&draw;[1], 63, 0, 127); |
|||
|
|||
// Enable background clear |
|||
draw[0].isbg = 1; |
|||
draw[1].isbg = 1; |
|||
|
|||
// Apply environments |
|||
PutDispEnv(&disp;[0]); |
|||
PutDrawEnv(&draw;[0]); |
|||
|
|||
// Make sure db starts with zero |
|||
db = 0; |
|||
|
|||
// Load the internal font texture |
|||
FntLoad(960, 0); |
|||
// Create the text stream |
|||
FntOpen(0, 8, 320, 224, 0, 100); |
|||
} |
|||
|
|||
void display(void) |
|||
{ |
|||
// Wait for GPU to finish drawing and V-Blank |
|||
DrawSync(0); |
|||
VSync(0); |
|||
|
|||
// Flip buffer counter |
|||
db = !db; |
|||
|
|||
// Apply environments |
|||
PutDispEnv(&disp;[db]); |
|||
PutDrawEnv(&draw;[db]); |
|||
|
|||
// Enable display |
|||
SetDispMask(1); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
// Initialize graphics and stuff |
|||
init(); |
|||
|
|||
// Main loop |
|||
while(1) |
|||
{ |
|||
FntPrint("HELLO WORLD!"); |
|||
|
|||
FntFlush(-1); |
|||
display(); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
|
|||
<h2 id="result">Result</h2> |
|||
<p>Run the program on the console or emulator and you should see a |
|||
dark purple picture:</p> |
|||
<img src="Chapter%201.1%20Setting%20up%20Graphics%20and%20Hello%20World_files/1-hello.png"> |
|||
|
|||
<h2 id="conclusion">Conclusion</h2> |
|||
<p>This concludes this chapter of Lameguy64's PSX Tutorial series. You should |
|||
be very familiar of how framebuffers are handled on the PSX hardware and |
|||
should be ready to take on drawing proper graphics primitives.</p> |
|||
<p>A few things you may want to experiment with this example yourself:</p> |
|||
<ul> |
|||
<li>Try ordering the areas side by side.</li> |
|||
<li>Go to the VRAM/GPU Viewer in no$psx or press F12 in PSXfin to visually |
|||
see the buffers in action. This also works for retail games.</li> |
|||
<li>Play around with the clear color values on the <b>DRAWENV</b> environments. |
|||
Make sure the color values on both <b>DRAWENV</b> elements are the same |
|||
otherwise intense flickering will occur.</li> |
|||
</ul> |
|||
<p>The next tutorial will cover how to draw graphics with the GPU using |
|||
ordering tables and primitive packets.</p> |
|||
<hr> |
|||
|
|||
<table class="footer-table" width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left">Previous</td> |
|||
<td width="20%" align="center"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter1/2-graphics.html">Next</a></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
|
|||
|
|||
</body></html> |
|||
<!-- |
|||
FILE ARCHIVED ON 03:35:33 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:40:14 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
--> |
|||
<!-- |
|||
playback timings (ms): |
|||
captures_list: 94.63 |
|||
exclusion.robots: 0.244 |
|||
exclusion.robots.policy: 0.234 |
|||
cdx.remote: 0.081 |
|||
esindex: 0.011 |
|||
LoadShardBlock: 61.049 (3) |
|||
PetaboxLoader3.datanode: 58.129 (4) |
|||
CDXLines.iter: 18.978 (3) |
|||
load_resource: 261.231 |
|||
PetaboxLoader3.resolve: 226.231 |
|||
--> |
|||
@ -0,0 +1,474 @@ |
|||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3.0
|
|||
/* eslint-disable no-var, semi, prefer-arrow-callback, prefer-template */ |
|||
|
|||
/** |
|||
* Collection of methods for sending analytics events to Archive.org's analytics server. |
|||
* |
|||
* These events are used for internal stats and sent (in anonymized form) to Google Analytics. |
|||
* |
|||
* @see analytics.md |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
window.archive_analytics = (function defineArchiveAnalytics() { |
|||
// keep orignal Date object so as not to be affected by wayback's
|
|||
// hijacking global Date object
|
|||
var Date = window.Date; |
|||
var ARCHIVE_ANALYTICS_VERSION = 2; |
|||
var DEFAULT_SERVICE = 'ao_2'; |
|||
var NO_SAMPLING_SERVICE = 'ao_no_sampling'; // sends every event instead of a percentage
|
|||
|
|||
var startTime = new Date(); |
|||
|
|||
/** |
|||
* @return {Boolean} |
|||
*/ |
|||
function isPerformanceTimingApiSupported() { |
|||
return 'performance' in window && 'timing' in window.performance; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the browser starting to parse the DOM and |
|||
* the current time. |
|||
* |
|||
* Uses the Performance API or a fallback value if it's not available. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number} |
|||
*/ |
|||
function getLoadTime() { |
|||
var start; |
|||
|
|||
if (isPerformanceTimingApiSupported()) |
|||
start = window.performance.timing.domLoading; |
|||
else |
|||
start = startTime.getTime(); |
|||
|
|||
return new Date().getTime() - start; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the user navigating to the page and |
|||
* the current time. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number|null} null if the browser doesn't support the Performance API |
|||
*/ |
|||
function getNavToDoneTime() { |
|||
if (!isPerformanceTimingApiSupported()) |
|||
return null; |
|||
|
|||
return new Date().getTime() - window.performance.timing.navigationStart; |
|||
} |
|||
|
|||
/** |
|||
* Performs an arithmetic calculation on a string with a number and unit, while maintaining |
|||
* the unit. |
|||
* |
|||
* @param {String} original value to modify, with a unit |
|||
* @param {Function} doOperation accepts one Number parameter, returns a Number |
|||
* @returns {String} |
|||
*/ |
|||
function computeWithUnit(original, doOperation) { |
|||
var number = parseFloat(original, 10); |
|||
var unit = original.replace(/(\d*\.\d+)|\d+/, ''); |
|||
|
|||
return doOperation(number) + unit; |
|||
} |
|||
|
|||
/** |
|||
* Computes the default font size of the browser. |
|||
* |
|||
* @returns {String|null} computed font-size with units (typically pixels), null if it cannot be computed |
|||
*/ |
|||
function getDefaultFontSize() { |
|||
var fontSizeStr; |
|||
|
|||
if (!('getComputedStyle' in window)) |
|||
return null; |
|||
|
|||
var style = window.getComputedStyle(document.documentElement); |
|||
if (!style) |
|||
return null; |
|||
|
|||
fontSizeStr = style.fontSize; |
|||
|
|||
// Don't modify the value if tracking book reader.
|
|||
if (document.querySelector('#BookReader')) |
|||
return fontSizeStr; |
|||
|
|||
return computeWithUnit(fontSizeStr, function reverseBootstrapFontSize(number) { |
|||
// Undo the 62.5% size applied in the Bootstrap CSS.
|
|||
return number * 1.6; |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Get the URL parameters for a given Location |
|||
* @param {Location} |
|||
* @return {Object} The URL parameters |
|||
*/ |
|||
function getParams(location) { |
|||
if (!location) location = window.location; |
|||
var vars; |
|||
var i; |
|||
var pair; |
|||
var params = {}; |
|||
var query = location.search; |
|||
if (!query) return params; |
|||
vars = query.substring(1).split('&'); |
|||
for (i = 0; i < vars.length; i++) { |
|||
pair = vars[i].split('='); |
|||
params[pair[0]] = decodeURIComponent(pair[1]); |
|||
} |
|||
return params; |
|||
} |
|||
|
|||
function getMetaProp(name) { |
|||
var metaTag = document.querySelector('meta[property=' + name + ']'); |
|||
return metaTag ? metaTag.getAttribute('content') || null : null; |
|||
} |
|||
|
|||
var ArchiveAnalytics = { |
|||
/** |
|||
* @type {String|null} |
|||
*/ |
|||
service: getMetaProp('service'), |
|||
mediaType: getMetaProp('mediatype'), |
|||
primaryCollection: getMetaProp('primary_collection'), |
|||
|
|||
/** |
|||
* Key-value pairs to send in pageviews (you can read this after a pageview to see what was |
|||
* sent). |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
values: {}, |
|||
|
|||
/** |
|||
* Sends an analytics ping, preferably using navigator.sendBeacon() |
|||
* @param {Object} values |
|||
* @param {Function} [onload_callback] (deprecated) callback to invoke once ping to analytics server is done |
|||
* @param {Boolean} [augment_for_ao_site] (deprecated) if true, add some archive.org site-specific values |
|||
*/ |
|||
send_ping: function send_ping(values, onload_callback, augment_for_ao_site) { |
|||
if (typeof window.navigator !== 'undefined' && typeof window.navigator.sendBeacon !== 'undefined') |
|||
this.send_ping_via_beacon(values); |
|||
else |
|||
this.send_ping_via_image(values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Beacon API |
|||
* NOTE: Assumes window.navigator.sendBeacon exists |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_beacon: function send_ping_via_beacon(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
window.navigator.sendBeacon(url); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Image object |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_image: function send_ping_via_image(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
var loadtime_img = new Image(1, 1); |
|||
loadtime_img.src = url; |
|||
loadtime_img.alt = ''; |
|||
}, |
|||
|
|||
/** |
|||
* Construct complete tracking URL containing payload |
|||
* @param {Object} params Tracking parameters to pass |
|||
* @return {String} URL to use for tracking call |
|||
*/ |
|||
generate_tracking_url: function generate_tracking_url(params) { |
|||
var baseUrl = '//analytics.archive.org/0.gif'; |
|||
var keys; |
|||
var outputParams = params; |
|||
var outputParamsArray = []; |
|||
|
|||
outputParams.service = outputParams.service || this.service || DEFAULT_SERVICE; |
|||
|
|||
// Build array of querystring parameters
|
|||
keys = Object.keys(outputParams); |
|||
keys.forEach(function keyIteration(key) { |
|||
outputParamsArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(outputParams[key])); |
|||
}); |
|||
outputParamsArray.push('version=' + ARCHIVE_ANALYTICS_VERSION); |
|||
outputParamsArray.push('count=' + (keys.length + 2)); // Include `version` and `count` in count
|
|||
|
|||
return baseUrl + '?' + outputParamsArray.join('&'); |
|||
}, |
|||
|
|||
/** |
|||
* @param {int} page Page number |
|||
*/ |
|||
send_scroll_fetch_event: function send_scroll_fetch_event(page) { |
|||
var additionalValues = { ev: page }; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
send_scroll_fetch_base_event: function send_scroll_fetch_base_event() { |
|||
var additionalValues = {}; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch_base', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} [options] |
|||
* @param {String} [options.mediaType] |
|||
* @param {String} [options.mediaLanguage] |
|||
* @param {String} [options.page] The path portion of the page URL |
|||
*/ |
|||
send_pageview: function send_pageview(options) { |
|||
var settings = options || {}; |
|||
|
|||
var defaultFontSize; |
|||
var loadTime = getLoadTime(); |
|||
var mediaType = settings.mediaType; |
|||
var primaryCollection = settings.primaryCollection; |
|||
var page = settings.page; |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
|
|||
/** |
|||
* @return {String} |
|||
*/ |
|||
function get_locale() { |
|||
if (navigator) { |
|||
if (navigator.language) |
|||
return navigator.language; |
|||
|
|||
else if (navigator.browserLanguage) |
|||
return navigator.browserLanguage; |
|||
|
|||
else if (navigator.systemLanguage) |
|||
return navigator.systemLanguage; |
|||
|
|||
else if (navigator.userLanguage) |
|||
return navigator.userLanguage; |
|||
} |
|||
return ''; |
|||
} |
|||
|
|||
defaultFontSize = getDefaultFontSize(); |
|||
|
|||
// Set field values
|
|||
this.values.kind = 'pageview'; |
|||
this.values.timediff = (new Date().getTimezoneOffset()/60)*(-1); // *timezone* diff from UTC
|
|||
this.values.locale = get_locale(); |
|||
this.values.referrer = (document.referrer == '' ? '-' : document.referrer); |
|||
|
|||
if (loadTime) |
|||
this.values.loadtime = loadTime; |
|||
|
|||
if (navToDoneTime) |
|||
this.values.nav_to_done_ms = navToDoneTime; |
|||
|
|||
if (settings.trackingId) { |
|||
this.values.ga_tid = settings.trackingId; |
|||
} |
|||
|
|||
/* START CUSTOM DIMENSIONS */ |
|||
if (defaultFontSize) |
|||
this.values.ga_cd1 = defaultFontSize; |
|||
|
|||
if ('devicePixelRatio' in window) |
|||
this.values.ga_cd2 = window.devicePixelRatio; |
|||
|
|||
if (mediaType) |
|||
this.values.ga_cd3 = mediaType; |
|||
|
|||
if (settings.mediaLanguage) { |
|||
this.values.ga_cd4 = settings.mediaLanguage; |
|||
} |
|||
|
|||
if (primaryCollection) { |
|||
this.values.ga_cd5 = primaryCollection; |
|||
} |
|||
/* END CUSTOM DIMENSIONS */ |
|||
|
|||
if (page) |
|||
this.values.page = page; |
|||
|
|||
this.send_ping(this.values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a tracking "Event". |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event: function send_event( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
if (!label) label = window.location.pathname; |
|||
if (!additionalEventParams) additionalEventParams = {}; |
|||
if (additionalEventParams.mediaLanguage) { |
|||
additionalEventParams.ga_cd4 = additionalEventParams.mediaLanguage; |
|||
delete additionalEventParams.mediaLanguage; |
|||
} |
|||
var eventParams = Object.assign( |
|||
{ |
|||
kind: 'event', |
|||
ec: category, |
|||
ea: action, |
|||
el: label, |
|||
cache_bust: Math.random(), |
|||
}, |
|||
additionalEventParams |
|||
); |
|||
this.send_ping(eventParams); |
|||
}, |
|||
|
|||
/** |
|||
* Sends every event instead of a small percentage. |
|||
* |
|||
* Use this sparingly as it can generate a lot of events. |
|||
* |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event_no_sampling: function send_event_no_sampling( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
var extraParams = additionalEventParams || {}; |
|||
extraParams.service = NO_SAMPLING_SERVICE; |
|||
this.send_event(category, action, label, extraParams); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} options see this.send_pageview options |
|||
*/ |
|||
send_pageview_on_load: function send_pageview_on_load(options) { |
|||
var self = this; |
|||
window.addEventListener('load', function send_pageview_with_options() { |
|||
self.send_pageview(options); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* Handles tracking events passed in URL. |
|||
* Assumes category and action values are separated by a "|" character. |
|||
* NOTE: Uses the unsampled analytics property. Watch out for future high click links! |
|||
* @param {Location} |
|||
*/ |
|||
process_url_events: function process_url_events(location) { |
|||
var eventValues; |
|||
var actionValue; |
|||
var eventValue = getParams(location).iax; |
|||
if (!eventValue) return; |
|||
eventValues = eventValue.split('|'); |
|||
actionValue = eventValues.length >= 1 ? eventValues[1] : ''; |
|||
this.send_event_no_sampling( |
|||
eventValues[0], |
|||
actionValue, |
|||
window.location.pathname |
|||
); |
|||
}, |
|||
|
|||
/** |
|||
* Attaches handlers for event tracking. |
|||
* |
|||
* To enable click tracking for a link, add a `data-event-click-tracking` |
|||
* attribute containing the Google Analytics Event Category and Action, separated |
|||
* by a vertical pipe (|). |
|||
* e.g. `<a href="foobar" data-event-click-tracking="TopNav|FooBar">` |
|||
* |
|||
* To enable form submit tracking, add a `data-event-form-tracking` attribute |
|||
* to the `form` tag. |
|||
* e.g. `<form data-event-form-tracking="TopNav|SearchForm" method="GET">` |
|||
* |
|||
* Additional tracking options can be added via a `data-event-tracking-options` |
|||
* parameter. This parameter, if included, should be a JSON string of the parameters. |
|||
* Valid parameters are: |
|||
* - service {string}: Corresponds to the Google Analytics property data values flow into |
|||
*/ |
|||
set_up_event_tracking: function set_up_event_tracking() { |
|||
var self = this; |
|||
var clickTrackingAttributeName = 'event-click-tracking'; |
|||
var formTrackingAttributeName = 'event-form-tracking'; |
|||
var trackingOptionsAttributeName = 'event-tracking-options'; |
|||
|
|||
function handleAction(event, attributeName) { |
|||
var selector = '[data-' + attributeName + ']'; |
|||
var eventTarget = event.target; |
|||
if (!eventTarget) return; |
|||
var target = eventTarget.closest(selector); |
|||
if (!target) return; |
|||
var categoryAction; |
|||
var categoryActionParts; |
|||
var options; |
|||
categoryAction = target.dataset[toCamelCase(attributeName)]; |
|||
if (!categoryAction) return; |
|||
categoryActionParts = categoryAction.split('|'); |
|||
options = target.dataset[toCamelCase(trackingOptionsAttributeName)]; |
|||
options = options ? JSON.parse(options) : {}; |
|||
self.send_event( |
|||
categoryActionParts[0], |
|||
categoryActionParts[1], |
|||
categoryActionParts[2] || window.location.pathname, |
|||
options.service ? { service: options.service } : {} |
|||
); |
|||
} |
|||
|
|||
function toCamelCase(str) { |
|||
return str.replace(/\W+(.)/g, function (match, chr) { |
|||
return chr.toUpperCase(); |
|||
}); |
|||
}; |
|||
|
|||
document.addEventListener('click', function(e) { |
|||
handleAction(e, clickTrackingAttributeName); |
|||
}); |
|||
|
|||
document.addEventListener('submit', function(e) { |
|||
handleAction(e, formTrackingAttributeName); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* @returns {Object[]} |
|||
*/ |
|||
get_data_packets: function get_data_packets() { |
|||
return [this.values]; |
|||
}, |
|||
|
|||
/** |
|||
* Creates a tracking image for tracking JS compatibility. |
|||
* |
|||
* @param {string} type The type value for track_js_case in query params for 0.gif |
|||
*/ |
|||
create_tracking_image: function create_tracking_image(type) { |
|||
this.send_ping_via_image({ |
|||
cache_bust: Math.random(), |
|||
kind: 'track_js', |
|||
track_js_case: type, |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
return ArchiveAnalytics; |
|||
}()); |
|||
// @license-end
|
|||
@ -0,0 +1,500 @@ |
|||
@import 'record.css'; /* for SPN1 */ |
|||
|
|||
#wm-ipp-base { |
|||
height:65px;/* initial height just in case js code fails */ |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
background:none transparent; |
|||
} |
|||
#wm-ipp { |
|||
z-index: 2147483647; |
|||
} |
|||
#wm-ipp, #wm-ipp * { |
|||
font-family:Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size:12px; |
|||
line-height:1.2; |
|||
letter-spacing:0; |
|||
width:auto; |
|||
height:auto; |
|||
max-width:none; |
|||
max-height:none; |
|||
min-width:0 !important; |
|||
min-height:0; |
|||
outline:none; |
|||
float:none; |
|||
text-align:left; |
|||
border:none; |
|||
color: #000; |
|||
text-indent: 0; |
|||
position: initial; |
|||
background: none; |
|||
} |
|||
#wm-ipp div, #wm-ipp canvas { |
|||
display: block; |
|||
} |
|||
#wm-ipp div, #wm-ipp tr, #wm-ipp td, #wm-ipp a, #wm-ipp form { |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
border-radius:0; |
|||
background-color:transparent; |
|||
background-image:none; |
|||
/*z-index:2147483640;*/ |
|||
height:auto; |
|||
} |
|||
#wm-ipp table { |
|||
border:none; |
|||
border-collapse:collapse; |
|||
margin:0; |
|||
padding:0; |
|||
width:auto; |
|||
font-size:inherit; |
|||
} |
|||
#wm-ipp form input { |
|||
padding:1px !important; |
|||
height:auto; |
|||
display:inline; |
|||
margin:0; |
|||
color: #000; |
|||
background: none #fff; |
|||
border: 1px solid #666; |
|||
} |
|||
#wm-ipp form input[type=submit] { |
|||
padding:0 8px !important; |
|||
margin:1px 0 1px 5px !important; |
|||
width:auto !important; |
|||
border: 1px solid #000 !important; |
|||
background: #fff !important; |
|||
color: #000 !important; |
|||
} |
|||
#wm-ipp a { |
|||
display: inline; |
|||
} |
|||
#wm-ipp a:hover{ |
|||
text-decoration:underline; |
|||
} |
|||
#wm-ipp a.wm-btn:hover { |
|||
text-decoration:none; |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp a.wm-btn:hover span { |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp #wm-ipp-inside { |
|||
margin: 0 6px; |
|||
border:5px solid #000; |
|||
border-top:none; |
|||
background-color:rgba(255,255,255,0.9); |
|||
-moz-box-shadow:1px 1px 4px #333; |
|||
-webkit-box-shadow:1px 1px 4px #333; |
|||
box-shadow:1px 1px 4px #333; |
|||
border-radius:0 0 8px 8px; |
|||
} |
|||
/* selectors are intentionally verbose to ensure priority */ |
|||
#wm-ipp #wm-logo { |
|||
padding:0 10px; |
|||
vertical-align:middle; |
|||
min-width:100px; |
|||
flex: 0 0 100px; |
|||
} |
|||
#wm-ipp .c { |
|||
padding-left: 4px; |
|||
} |
|||
#wm-ipp .c .u { |
|||
margin-top: 4px !important; |
|||
} |
|||
#wm-ipp .n { |
|||
padding:0 0 0 5px !important; |
|||
vertical-align: bottom; |
|||
} |
|||
#wm-ipp .n a { |
|||
text-decoration:none; |
|||
color:#33f; |
|||
font-weight:bold; |
|||
} |
|||
#wm-ipp .n .b { |
|||
padding:0 6px 0 0 !important; |
|||
text-align:right !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n .y .b { |
|||
padding:0 6px 2px 0 !important; |
|||
} |
|||
#wm-ipp .n .c { |
|||
background:#000; |
|||
color:#ff0; |
|||
font-weight:bold; |
|||
padding:0 !important; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp.hi .n td.c { |
|||
color:#ec008c; |
|||
} |
|||
#wm-ipp .n td.f { |
|||
padding:0 0 0 6px !important; |
|||
text-align:left !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n tr.m td { |
|||
text-transform:uppercase; |
|||
white-space:nowrap; |
|||
padding:2px 0; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 0 0 !important; |
|||
vertical-align:bottom; |
|||
} |
|||
#wm-ipp #wm-nav-captures { |
|||
white-space: nowrap; |
|||
} |
|||
#wm-ipp .c .s a.t { |
|||
color:#33f; |
|||
font-weight:bold; |
|||
line-height: 1.8; |
|||
} |
|||
#wm-ipp .c .s div.r { |
|||
color: #666; |
|||
font-size:9px; |
|||
white-space:nowrap; |
|||
} |
|||
#wm-ipp .c .k { |
|||
padding-bottom:1px; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayMonthEl { |
|||
padding: 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayYearEl { |
|||
padding: 0 0 2px 0 !important; |
|||
} |
|||
|
|||
div#wm-ipp-sparkline { |
|||
position:relative;/* for positioning markers */ |
|||
white-space:nowrap; |
|||
background-color:#fff; |
|||
cursor:pointer; |
|||
line-height:0.9; |
|||
} |
|||
#sparklineImgId, #wm-sparkline-canvas { |
|||
position:relative; |
|||
z-index:9012; |
|||
max-width:none; |
|||
} |
|||
#wm-ipp-sparkline div.yt { |
|||
position:absolute; |
|||
z-index:9010 !important; |
|||
background-color:#ff0 !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp-sparkline div.mt { |
|||
position:absolute; |
|||
z-index:9013 !important; |
|||
background-color:#ec008c !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp .r { |
|||
margin-left: 4px; |
|||
} |
|||
#wm-ipp .r a { |
|||
color:#33f; |
|||
border:none; |
|||
position:relative; |
|||
background-color:transparent; |
|||
background-repeat:no-repeat !important; |
|||
background-position:100% 100% !important; |
|||
text-decoration: none; |
|||
} |
|||
#wm-ipp #wm-capinfo { |
|||
/* prevents notice div background from sticking into round corners of |
|||
#wm-ipp-inside */ |
|||
border-radius: 0 0 4px 4px; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo { |
|||
display:block; |
|||
float:left; |
|||
margin-right:3px; |
|||
width:90px; |
|||
min-height:90px; |
|||
max-height: 290px; |
|||
border-radius:45px; |
|||
overflow:hidden; |
|||
background-position:50%; |
|||
background-size:auto 90px; |
|||
box-shadow: 0 0 2px 2px rgba(208,208,208,128) inset; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo span { |
|||
display:inline-block; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo img { |
|||
height:90px; |
|||
position:relative; |
|||
left:-50%; |
|||
} |
|||
#wm-ipp #wm-capinfo .wm-title { |
|||
font-size:130%; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector { |
|||
display:inline-block; |
|||
color: #aaa; |
|||
text-decoration:none !important; |
|||
padding: 2px 8px; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector.selected { |
|||
background-color:#666; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector:hover { |
|||
color: #fff; |
|||
} |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-collected-by, |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-timestamps { |
|||
display: none; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content { |
|||
background-color:#ff0; |
|||
padding:5px; |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content * { |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-expand { |
|||
right: 1px; |
|||
bottom: -1px; |
|||
color: #ffffff; |
|||
background-color: #666 !important; |
|||
padding:0 5px 0 3px !important; |
|||
border-radius: 3px 3px 0 0 !important; |
|||
} |
|||
#wm-ipp #wm-expand span { |
|||
color: #ffffff; |
|||
} |
|||
#wm-ipp #wm-expand #wm-expand-icon { |
|||
display: inline-block; |
|||
transition: transform 0.5s; |
|||
transform-origin: 50% 45%; |
|||
} |
|||
#wm-ipp #wm-expand.wm-open #wm-expand-icon { |
|||
transform: rotate(180deg); |
|||
} |
|||
#wm-ipp #wmtb { |
|||
text-align:right; |
|||
} |
|||
#wm-ipp #wmtb #wmtbURL { |
|||
width: calc(100% - 45px); |
|||
} |
|||
#wm-ipp #wm-graph-anchor { |
|||
border-right:1px solid #ccc; |
|||
} |
|||
/* time coherence */ |
|||
html.wb-highlight { |
|||
box-shadow: inset 0 0 0 3px #a50e3a !important; |
|||
} |
|||
.wb-highlight { |
|||
outline: 3px solid #a50e3a !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:none !important; |
|||
} |
|||
@media print { |
|||
#wm-ipp-base { |
|||
display:none !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:block !important; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
} |
|||
@media (max-width:414px) { |
|||
#wm-ipp .xxs { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (min-width:1055px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:block !important; |
|||
} |
|||
} |
|||
@media (max-width:1054px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (max-width:1163px) { |
|||
#wm-logo { |
|||
display:none !important; |
|||
} |
|||
} |
|||
|
|||
#wm-btns { |
|||
white-space: nowrap; |
|||
margin-top: -2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-open { |
|||
margin-right: 7px; |
|||
top: -6px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in { |
|||
box-sizing: content-box; |
|||
display: none; |
|||
margin-right: 7px; |
|||
top: -8px; |
|||
|
|||
/* |
|||
round border around sign in button |
|||
*/ |
|||
border: 2px #000 solid; |
|||
border-radius: 14px; |
|||
padding-right: 2px; |
|||
padding-bottom: 2px; |
|||
width: 11px; |
|||
height: 11px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in>.iconochive-person { |
|||
font-size: 12.5px; |
|||
} |
|||
|
|||
#wm-save-snapshot-open > .iconochive-web { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-ipp #wm-share { |
|||
display: flex; |
|||
align-items: flex-end; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
#wm-share > #wm-screenshot { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-screenshot > .iconochive-image { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-share > #wm-video { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-video > .iconochive-movies { |
|||
color: #000; |
|||
display: inline-block; |
|||
font-size: 150%; |
|||
margin-bottom: 2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-in-progress { |
|||
display: none; |
|||
font-size:160%; |
|||
opacity: 0.5; |
|||
position: relative; |
|||
margin-right: 7px; |
|||
top: -5px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-success { |
|||
display: none; |
|||
color: green; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-fail { |
|||
display: none; |
|||
color: red; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
.wm-icon-screen-shot { |
|||
background: url("../images/web-screenshot.svg") no-repeat !important; |
|||
background-size: contain !important; |
|||
width: 22px !important; |
|||
height: 19px !important; |
|||
|
|||
display: inline-block; |
|||
} |
|||
#donato { |
|||
/* transition effect is disable so as to simplify height adjustment */ |
|||
/*transition: height 0.5s;*/ |
|||
height: 0; |
|||
margin: 0; |
|||
padding: 0; |
|||
border-bottom: 1px solid #999 !important; |
|||
} |
|||
body.wm-modal { |
|||
height: auto !important; |
|||
overflow: hidden !important; |
|||
} |
|||
#donato #donato-base { |
|||
width: 100%; |
|||
height: 100%; |
|||
/*bottom: 0;*/ |
|||
margin: 0; |
|||
padding: 0; |
|||
position: absolute; |
|||
z-index: 2147483639; |
|||
} |
|||
body.wm-modal #donato #donato-base { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 2147483640; |
|||
} |
|||
|
|||
.wb-autocomplete-suggestions { |
|||
font-family: Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size: 12px; |
|||
text-align: left; |
|||
cursor: default; |
|||
border: 1px solid #ccc; |
|||
border-top: 0; |
|||
background: #fff; |
|||
box-shadow: -1px 1px 3px rgba(0,0,0,.1); |
|||
position: absolute; |
|||
display: none; |
|||
z-index: 2147483647; |
|||
max-height: 254px; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
box-sizing: border-box; |
|||
} |
|||
.wb-autocomplete-suggestion { |
|||
position: relative; |
|||
padding: 0 .6em; |
|||
line-height: 23px; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
font-size: 1.02em; |
|||
color: #333; |
|||
} |
|||
.wb-autocomplete-suggestion b { |
|||
font-weight: bold; |
|||
} |
|||
.wb-autocomplete-suggestion.selected { |
|||
background: #f0f0f0; |
|||
} |
|||
@ -0,0 +1,147 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="512" |
|||
height="256" |
|||
viewBox="0 0 135.46666 67.733335" |
|||
version="1.1" |
|||
id="svg8" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="bufferlayout.svg"> |
|||
<defs |
|||
id="defs2" /> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1.979899" |
|||
inkscape:cx="315.19791" |
|||
inkscape:cy="0.98153187" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="false" |
|||
units="px" |
|||
inkscape:snap-bbox="true" |
|||
inkscape:bbox-nodes="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-256,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,67.733332" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,67.733332" |
|||
orientation="256,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title></dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-229.26665)"> |
|||
<rect |
|||
y="260.88434" |
|||
x="-0.13229166" |
|||
height="31.75" |
|||
width="42.333332" |
|||
id="rect4519" |
|||
style="opacity:1;fill:#008080;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#00ffff;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4517" |
|||
width="42.333332" |
|||
height="31.75" |
|||
x="-0.13229166" |
|||
y="229.13435" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="135.46666" |
|||
height="67.73333" |
|||
x="0" |
|||
y="229.26665" |
|||
rx="2.0798286e-006" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="0.28663194" |
|||
y="231.93729" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="0.28663194" |
|||
y="231.93729" |
|||
style="font-size:2.82222223px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">(0,0)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="135.18141" |
|||
y="296.09872" |
|||
id="text4497-5"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495-0" |
|||
x="135.18141" |
|||
y="296.09872" |
|||
style="font-size:2.82222223px;text-align:end;text-anchor:end;fill:#000000;stroke:none;stroke-width:0.26458332">(1023,511)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="20.906906" |
|||
y="246.06149" |
|||
id="text4523"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4521" |
|||
x="20.906906" |
|||
y="246.06149" |
|||
style="fill:#000000;stroke-width:0.26458332">Buffer A</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="20.9951" |
|||
y="277.81146" |
|||
id="text4523-1"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4521-6" |
|||
x="20.9951" |
|||
y="277.81146" |
|||
style="fill:#ffffff;stroke-width:0.26458332">Buffer B</tspan></text> |
|||
</g> |
|||
</svg> |
|||
3
Docs/Chapter 1.1 Setting up Graphics and Hello World_files/bundle-playback.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,286 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="510" |
|||
height="320" |
|||
viewBox="0 0 134.93749 84.666663" |
|||
version="1.1" |
|||
id="svg8" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="gpudiagram.svg"> |
|||
<title |
|||
id="title4564">CPU - GPU Block Diagram</title> |
|||
<defs |
|||
id="defs2" /> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1.2973752" |
|||
inkscape:cx="315.52982" |
|||
inkscape:cy="174.85259" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="true" |
|||
inkscape:snap-text-baseline="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
units="px" |
|||
showguides="true"> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid4485" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title>CPU - GPU Block Diagram</dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-212.33332)"> |
|||
<path |
|||
sodipodi:nodetypes="sccccs" |
|||
inkscape:connector-curvature="0" |
|||
id="path4580" |
|||
d="m 109.8021,254.66666 c 0,-5.29166 5.29166,-5.29166 5.29166,-5.29166 l 15.87499,-1e-5 v 10.58333 l -15.87499,10e-6 c 0,0 -5.29166,0 -5.29166,-5.29167 z" |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4576" |
|||
width="21.166666" |
|||
height="9.2604113" |
|||
x="80.697914" |
|||
y="228.20833" /> |
|||
<rect |
|||
y="228.20833" |
|||
x="34.395832" |
|||
height="9.2604113" |
|||
width="21.166666" |
|||
id="rect4574" |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4572" |
|||
width="21.166666" |
|||
height="21.166666" |
|||
x="80.697914" |
|||
y="244.08331" /> |
|||
<rect |
|||
y="244.08333" |
|||
x="34.395832" |
|||
height="21.166666" |
|||
width="21.166666" |
|||
id="rect4570" |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4568" |
|||
width="21.166666" |
|||
height="21.166666" |
|||
x="34.395832" |
|||
y="271.86456" /> |
|||
<rect |
|||
y="244.08333" |
|||
x="6.614584" |
|||
height="21.166666" |
|||
width="21.166666" |
|||
id="rect4566" |
|||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4491" |
|||
width="21.166666" |
|||
height="21.166666" |
|||
x="79.375008" |
|||
y="242.76042" /> |
|||
<rect |
|||
y="226.88544" |
|||
x="79.375008" |
|||
height="9.2604113" |
|||
width="21.166666" |
|||
id="rect4540" |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4524" |
|||
width="21.166666" |
|||
height="9.2604113" |
|||
x="33.072918" |
|||
y="226.88544" /> |
|||
<rect |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4491-9" |
|||
width="21.166666" |
|||
height="21.166666" |
|||
x="33.072918" |
|||
y="242.76042" /> |
|||
<rect |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4556" |
|||
width="21.166666" |
|||
height="21.166666" |
|||
x="5.2916675" |
|||
y="242.76041" /> |
|||
<rect |
|||
y="270.54169" |
|||
x="33.072918" |
|||
height="21.166666" |
|||
width="21.166666" |
|||
id="rect4518" |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.52916676;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.11111069px;line-height:1.25;font-family:HandelGotDLig;-inkscape-font-specification:HandelGotDLig;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.11666656;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="89.958336" |
|||
y="254.66667" |
|||
id="text4489"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4487" |
|||
x="89.958336" |
|||
y="254.66667" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:2.11666656">GPU</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.11111069px;line-height:1.25;font-family:HandelGotDLig;-inkscape-font-specification:HandelGotDLig;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.11666656;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="43.656254" |
|||
y="254.66667" |
|||
id="text4489-4"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4487-6" |
|||
x="43.656254" |
|||
y="254.66667" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:2.11666656">CPU</tspan></text> |
|||
<text |
|||
id="text4516" |
|||
y="282.44794" |
|||
x="43.656254" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.11111069px;line-height:1.25;font-family:HandelGotDLig;-inkscape-font-specification:HandelGotDLig;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.11666656;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:2.11666656" |
|||
y="282.44794" |
|||
x="43.656254" |
|||
id="tspan4514" |
|||
sodipodi:role="line">GTE</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="43.65625" |
|||
y="233.50002" |
|||
id="text4522"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4520" |
|||
x="43.65625" |
|||
y="233.50002" |
|||
style="fill:#000000;stroke:none;stroke-width:0.52916664">RAM</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 43.656254,270.54166 v -6.61458" |
|||
id="path4526" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 43.656254,242.76041 v -6.61458" |
|||
id="path4528" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 108.47918,253.34374 c 0,-5.29166 5.29166,-5.29166 5.29166,-5.29166 l 15.87499,-1e-5 v 10.58333 l -15.87499,10e-6 c 0,0 -5.29166,0 -5.29166,-5.29167 z" |
|||
id="path4530" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="sccccs" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.11666656;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 67.46875,291.70832 0,-64.82292" |
|||
id="path4532" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="M 54.239587,253.34374 H 79.375004" |
|||
id="path4534" |
|||
inkscape:connector-curvature="0" /> |
|||
<text |
|||
id="text4538" |
|||
y="233.50002" |
|||
x="89.958351" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="fill:#000000;stroke:none;stroke-width:0.52916664" |
|||
y="233.50002" |
|||
x="89.958351" |
|||
id="tspan4536" |
|||
sodipodi:role="line">VRAM</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 89.958335,242.76041 v -6.61458" |
|||
id="path4542" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 100.54168,253.34374 h 7.9375" |
|||
id="path4544" |
|||
inkscape:connector-curvature="0" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="67.46875" |
|||
y="225.56248" |
|||
id="text4548"><tspan |
|||
sodipodi:role="line" |
|||
x="67.46875" |
|||
y="225.56248" |
|||
style="line-height:1.25;fill:#000000;stroke:none;stroke-width:0.52916664" |
|||
id="tspan4550">Bus</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.11111069px;line-height:1.25;font-family:HandelGotDLig;-inkscape-font-specification:HandelGotDLig;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.11666656;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="15.875003" |
|||
y="254.66666" |
|||
id="text4554"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4552" |
|||
x="15.875003" |
|||
y="254.66666" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:2.11666656">MDEC</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 26.458333,253.34375 h 6.614583" |
|||
id="path4558" |
|||
inkscape:connector-curvature="0" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="119.0625" |
|||
y="254.66666" |
|||
id="text4562"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4560" |
|||
x="119.0625" |
|||
y="254.66666" |
|||
style="text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.52916664">Video</tspan></text> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,116 @@ |
|||
@font-face{font-family:'Iconochive-Regular';src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?-ccsheb');src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?#iefix-ccsheb') format('embedded-opentype'),url('https://archive.org/includes/fonts/Iconochive-Regular.woff?-ccsheb') format('woff'),url('https://archive.org/includes/fonts/Iconochive-Regular.ttf?-ccsheb') format('truetype'),url('https://archive.org/includes/fonts/Iconochive-Regular.svg?-ccsheb#Iconochive-Regular') format('svg');font-weight:normal;font-style:normal} |
|||
[class^="iconochive-"],[class*=" iconochive-"]{font-family:'Iconochive-Regular'!important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} |
|||
.iconochive-Uplevel:before{content:"\21b5"} |
|||
.iconochive-exit:before{content:"\1f6a3"} |
|||
.iconochive-beta:before{content:"\3b2"} |
|||
.iconochive-logo:before{content:"\1f3db"} |
|||
.iconochive-audio:before{content:"\1f568"} |
|||
.iconochive-movies:before{content:"\1f39e"} |
|||
.iconochive-software:before{content:"\1f4be"} |
|||
.iconochive-texts:before{content:"\1f56e"} |
|||
.iconochive-etree:before{content:"\1f3a4"} |
|||
.iconochive-image:before{content:"\1f5bc"} |
|||
.iconochive-web:before{content:"\1f5d4"} |
|||
.iconochive-collection:before{content:"\2211"} |
|||
.iconochive-folder:before{content:"\1f4c2"} |
|||
.iconochive-data:before{content:"\1f5c3"} |
|||
.iconochive-tv:before{content:"\1f4fa"} |
|||
.iconochive-article:before{content:"\1f5cf"} |
|||
.iconochive-question:before{content:"\2370"} |
|||
.iconochive-question-dark:before{content:"\3f"} |
|||
.iconochive-info:before{content:"\69"} |
|||
.iconochive-info-small:before{content:"\24d8"} |
|||
.iconochive-comment:before{content:"\1f5e9"} |
|||
.iconochive-comments:before{content:"\1f5ea"} |
|||
.iconochive-person:before{content:"\1f464"} |
|||
.iconochive-people:before{content:"\1f465"} |
|||
.iconochive-eye:before{content:"\1f441"} |
|||
.iconochive-rss:before{content:"\221e"} |
|||
.iconochive-time:before{content:"\1f551"} |
|||
.iconochive-quote:before{content:"\275d"} |
|||
.iconochive-disc:before{content:"\1f4bf"} |
|||
.iconochive-tv-commercial:before{content:"\1f4b0"} |
|||
.iconochive-search:before{content:"\1f50d"} |
|||
.iconochive-search-star:before{content:"\273d"} |
|||
.iconochive-tiles:before{content:"\229e"} |
|||
.iconochive-list:before{content:"\21f6"} |
|||
.iconochive-list-bulleted:before{content:"\2317"} |
|||
.iconochive-latest:before{content:"\2208"} |
|||
.iconochive-left:before{content:"\2c2"} |
|||
.iconochive-right:before{content:"\2c3"} |
|||
.iconochive-left-solid:before{content:"\25c2"} |
|||
.iconochive-right-solid:before{content:"\25b8"} |
|||
.iconochive-up-solid:before{content:"\25b4"} |
|||
.iconochive-down-solid:before{content:"\25be"} |
|||
.iconochive-dot:before{content:"\23e4"} |
|||
.iconochive-dots:before{content:"\25a6"} |
|||
.iconochive-columns:before{content:"\25af"} |
|||
.iconochive-sort:before{content:"\21d5"} |
|||
.iconochive-atoz:before{content:"\1f524"} |
|||
.iconochive-ztoa:before{content:"\1f525"} |
|||
.iconochive-upload:before{content:"\1f4e4"} |
|||
.iconochive-download:before{content:"\1f4e5"} |
|||
.iconochive-favorite:before{content:"\2605"} |
|||
.iconochive-heart:before{content:"\2665"} |
|||
.iconochive-play:before{content:"\25b6"} |
|||
.iconochive-play-framed:before{content:"\1f3ac"} |
|||
.iconochive-fullscreen:before{content:"\26f6"} |
|||
.iconochive-mute:before{content:"\1f507"} |
|||
.iconochive-unmute:before{content:"\1f50a"} |
|||
.iconochive-share:before{content:"\1f381"} |
|||
.iconochive-edit:before{content:"\270e"} |
|||
.iconochive-reedit:before{content:"\2710"} |
|||
.iconochive-gear:before{content:"\2699"} |
|||
.iconochive-remove-circle:before{content:"\274e"} |
|||
.iconochive-plus-circle:before{content:"\1f5d6"} |
|||
.iconochive-minus-circle:before{content:"\1f5d5"} |
|||
.iconochive-x:before{content:"\1f5d9"} |
|||
.iconochive-fork:before{content:"\22d4"} |
|||
.iconochive-trash:before{content:"\1f5d1"} |
|||
.iconochive-warning:before{content:"\26a0"} |
|||
.iconochive-flash:before{content:"\1f5f2"} |
|||
.iconochive-world:before{content:"\1f5fa"} |
|||
.iconochive-lock:before{content:"\1f512"} |
|||
.iconochive-unlock:before{content:"\1f513"} |
|||
.iconochive-twitter:before{content:"\1f426"} |
|||
.iconochive-facebook:before{content:"\66"} |
|||
.iconochive-googleplus:before{content:"\67"} |
|||
.iconochive-reddit:before{content:"\1f47d"} |
|||
.iconochive-tumblr:before{content:"\54"} |
|||
.iconochive-pinterest:before{content:"\1d4df"} |
|||
.iconochive-popcorn:before{content:"\1f4a5"} |
|||
.iconochive-email:before{content:"\1f4e7"} |
|||
.iconochive-embed:before{content:"\1f517"} |
|||
.iconochive-gamepad:before{content:"\1f579"} |
|||
.iconochive-Zoom_In:before{content:"\2b"} |
|||
.iconochive-Zoom_Out:before{content:"\2d"} |
|||
.iconochive-RSS:before{content:"\1f4e8"} |
|||
.iconochive-Light_Bulb:before{content:"\1f4a1"} |
|||
.iconochive-Add:before{content:"\2295"} |
|||
.iconochive-Tab_Activity:before{content:"\2318"} |
|||
.iconochive-Forward:before{content:"\23e9"} |
|||
.iconochive-Backward:before{content:"\23ea"} |
|||
.iconochive-No_Audio:before{content:"\1f508"} |
|||
.iconochive-Pause:before{content:"\23f8"} |
|||
.iconochive-No_Favorite:before{content:"\2606"} |
|||
.iconochive-Unike:before{content:"\2661"} |
|||
.iconochive-Song:before{content:"\266b"} |
|||
.iconochive-No_Flag:before{content:"\2690"} |
|||
.iconochive-Flag:before{content:"\2691"} |
|||
.iconochive-Done:before{content:"\2713"} |
|||
.iconochive-Check:before{content:"\2714"} |
|||
.iconochive-Refresh:before{content:"\27f3"} |
|||
.iconochive-Headphones:before{content:"\1f3a7"} |
|||
.iconochive-Chart:before{content:"\1f4c8"} |
|||
.iconochive-Bookmark:before{content:"\1f4d1"} |
|||
.iconochive-Documents:before{content:"\1f4da"} |
|||
.iconochive-Newspaper:before{content:"\1f4f0"} |
|||
.iconochive-Podcast:before{content:"\1f4f6"} |
|||
.iconochive-Radio:before{content:"\1f4fb"} |
|||
.iconochive-Cassette:before{content:"\1f4fc"} |
|||
.iconochive-Shuffle:before{content:"\1f500"} |
|||
.iconochive-Loop:before{content:"\1f501"} |
|||
.iconochive-Low_Audio:before{content:"\1f509"} |
|||
.iconochive-First:before{content:"\1f396"} |
|||
.iconochive-Invisible:before{content:"\1f576"} |
|||
.iconochive-Computer:before{content:"\1f5b3"} |
|||
@ -0,0 +1,70 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
/* |
|||
FILE ARCHIVED ON 03:35:25 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:39:09 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
*/ |
|||
/* |
|||
playback timings (ms): |
|||
captures_list: 107.165 |
|||
exclusion.robots: 0.073 |
|||
exclusion.robots.policy: 0.067 |
|||
cdx.remote: 0.064 |
|||
esindex: 0.009 |
|||
LoadShardBlock: 52.713 (3) |
|||
PetaboxLoader3.datanode: 140.466 (4) |
|||
CDXLines.iter: 14.771 (3) |
|||
load_resource: 139.896 |
|||
PetaboxLoader3.resolve: 47.824 |
|||
*/ |
|||
@ -0,0 +1,261 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="512" |
|||
height="256" |
|||
viewBox="0 0 135.46666 67.733335" |
|||
version="1.1" |
|||
id="svg8" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="vram-layout.svg"> |
|||
<defs |
|||
id="defs2" /> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="0.64868761" |
|||
inkscape:cx="283.23648" |
|||
inkscape:cy="175.65817" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="true" |
|||
units="px" |
|||
inkscape:snap-bbox="true" |
|||
inkscape:bbox-nodes="false" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:snap-text-baseline="true" |
|||
showguides="false" |
|||
inkscape:pagecheckerboard="false" |
|||
borderlayer="true"> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid5145" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title></dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-229.26665)"> |
|||
<rect |
|||
y="260.75208" |
|||
x="0" |
|||
height="31.487331" |
|||
width="42.070667" |
|||
id="rect4519" |
|||
style="opacity:1;fill:#008080;fill-opacity:1;stroke:#000000;stroke-width:0.26266789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-width:0.26226139;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4517" |
|||
width="42.071072" |
|||
height="31.48774" |
|||
x="0" |
|||
y="229.26665" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="135.46666" |
|||
height="67.73333" |
|||
x="7.1207683e-006" |
|||
y="229.26666" |
|||
rx="2.0798286e-006" |
|||
ry="2.0798286e-006" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="0.28663194" |
|||
y="231.93729" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="0.28663194" |
|||
y="231.93729" |
|||
style="font-size:2.82222223px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">(0,0)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="135.18141" |
|||
y="296.09872" |
|||
id="text4497-5"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495-0" |
|||
x="135.18141" |
|||
y="296.09872" |
|||
style="font-size:2.82222223px;text-align:end;text-anchor:end;fill:#000000;stroke:none;stroke-width:0.26458332">(1023,511)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="20.906906" |
|||
y="246.06149" |
|||
id="text4523"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4521" |
|||
x="20.906906" |
|||
y="246.06149" |
|||
style="fill:#000000;stroke-width:0.26458332">Buffer A</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="20.9951" |
|||
y="277.81146" |
|||
id="text4523-1"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4521-6" |
|||
x="20.9951" |
|||
y="277.81146" |
|||
style="fill:#ffffff;stroke-width:0.26458332">Buffer B</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:0.26378265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5147" |
|||
width="42.068748" |
|||
height="4.7624955" |
|||
x="0" |
|||
y="292.23749" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="19.84375" |
|||
y="295.67706" |
|||
id="text5151"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5149" |
|||
x="19.84375" |
|||
y="295.67706" |
|||
style="font-size:2.82222223px;fill:#000000;stroke:none;stroke-width:0.52916664">CLUTS</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.26253229;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5153" |
|||
width="33.602085" |
|||
height="33.868713" |
|||
x="42.068748" |
|||
y="229.2646" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="59.267689" |
|||
y="246.46355" |
|||
id="text5161"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5159" |
|||
x="59.267689" |
|||
y="246.46355" |
|||
style="fill:#000000;stroke-width:0.52916664">Textures</tspan></text> |
|||
<rect |
|||
y="229.2646" |
|||
x="75.67083" |
|||
height="33.868713" |
|||
width="33.602085" |
|||
id="rect5163" |
|||
style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.26253229;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5167" |
|||
y="246.46356" |
|||
x="93.134361" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="fill:#000000;stroke-width:0.52916664" |
|||
y="246.46356" |
|||
x="93.134361" |
|||
id="tspan5165" |
|||
sodipodi:role="line">Textures</tspan></text> |
|||
<rect |
|||
y="263.13333" |
|||
x="42.068748" |
|||
height="33.866684" |
|||
width="33.604134" |
|||
id="rect5183" |
|||
style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.26253229;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5187" |
|||
y="280.59479" |
|||
x="59.267689" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="fill:#000000;stroke-width:0.52916664" |
|||
y="280.59479" |
|||
x="59.267689" |
|||
id="tspan5185" |
|||
sodipodi:role="line">Textures</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.26253229;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5189" |
|||
width="33.60413" |
|||
height="33.866653" |
|||
x="75.67083" |
|||
y="263.13333" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="93.134361" |
|||
y="280.59479" |
|||
id="text5193"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5191" |
|||
x="93.134361" |
|||
y="280.59479" |
|||
style="fill:#000000;stroke-width:0.52916664">Textures</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5195" |
|||
width="13.229165" |
|||
height="20.108335" |
|||
x="109.27292" |
|||
y="229.26665" /> |
|||
<rect |
|||
style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5199" |
|||
width="12.964583" |
|||
height="20.108335" |
|||
x="122.50208" |
|||
y="229.26665" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="115.8875" |
|||
y="240.11456" |
|||
id="text5203"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5201" |
|||
x="115.8875" |
|||
y="240.11456" |
|||
style="fill:#000000;stroke-width:0.52916664">Textures</tspan></text> |
|||
<text |
|||
id="text5207" |
|||
y="240.11456" |
|||
x="129.11667" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="fill:#000000;stroke-width:0.52916664" |
|||
y="240.11456" |
|||
x="129.11667" |
|||
id="tspan5205" |
|||
sodipodi:role="line">Textures</tspan></text> |
|||
</g> |
|||
</svg> |
|||
21
Docs/Chapter 1.1 Setting up Graphics and Hello World_files/wombat.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,413 @@ |
|||
<html><head><script src="Chapter%201.2%20Drawing%20Graphics_files/analytics.js" type="text/javascript"></script> |
|||
<script type="text/javascript">window.addEventListener('DOMContentLoaded',function(){var v=archive_analytics.values;v.service='wb';v.server_name='wwwb-app228.us.archive.org';v.server_ms=369;archive_analytics.send_pageview({});});</script> |
|||
<script type="text/javascript" src="Chapter%201.2%20Drawing%20Graphics_files/bundle-playback.js" charset="utf-8"></script> |
|||
<script type="text/javascript" src="Chapter%201.2%20Drawing%20Graphics_files/wombat.js" charset="utf-8"></script> |
|||
<script type="text/javascript"> |
|||
__wm.init("http://web.archive.org/web"); |
|||
__wm.wombat("http://lameguy64.net/tutorials/pstutorials/chapter1/2-graphics.html","20220827033534","http://web.archive.org/","web","/_static/", |
|||
"1661571334"); |
|||
</script> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.2%20Drawing%20Graphics_files/banner-styles.css"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.2%20Drawing%20Graphics_files/iconochive.css"> |
|||
<!-- End Wayback Rewrite JS Include --> |
|||
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.2%20Drawing%20Graphics_files/style.css"> |
|||
<title>Chapter 1.2: Drawing Graphics</title><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></head> |
|||
|
|||
|
|||
<body><!-- BEGIN WAYBACK TOOLBAR INSERT --> |
|||
<style type="text/css"> |
|||
body { |
|||
margin-top:0 !important; |
|||
padding-top:0 !important; |
|||
/*min-width:800px !important;*/ |
|||
} |
|||
</style> |
|||
<script>__wm.rw(0);</script> |
|||
<div id="wm-ipp-base" style="display: block; direction: ltr; height: 1px;" lang="en"> |
|||
</div><div id="wm-ipp-print">The Wayback Machine - |
|||
http://web.archive.org/web/20220827033534/http://lameguy64.net/tutorials/pstutorials/chapter1/2-graphics.html</div> |
|||
<script type="text/javascript">//<![CDATA[ |
|||
__wm.bt(675,27,25,2,"web","http://lameguy64.net/tutorials/pstutorials/chapter1/2-graphics.html","20220827033534",1996,"/_static/",["/_static/css/banner-styles.css?v=fantwOh2","/_static/css/iconochive.css?v=qtvMKcIJ"], false); |
|||
__wm.rw(1); |
|||
//]]></script> |
|||
<!-- END WAYBACK TOOLBAR INSERT --> |
|||
|
|||
<h1>1.2. Drawing Graphics</h1> |
|||
<p>This tutorial will teach you how to draw graphics primitives with the GPU |
|||
using an ordering table and primitive packets. This is a very essential part |
|||
to learn about the PS1 as you need graphics to do anything on the console |
|||
really.</p> |
|||
<p>Just like in the last tutorial, libgs will not be covered here. Also, the |
|||
GPU is not responsible for 3D graphics. While it does render out (affine) |
|||
polygon all the 3D processing is actually done in a co-processor, called |
|||
the GTE or Geometry Transformation Engine.</p> |
|||
<p><b><i>Trivia:</i></b> The easiest way to tell if a person is not a PS1 programmer |
|||
is if they call the GTE the Geometry <i>Transfer</i> Engine instead of |
|||
<b>Transformation</b> Engine. The GTE does NOT transfer anything, it is |
|||
essentially like a math co-processor on the CPU as nothing but the CPU has |
|||
access to it, and it does nothing else but vector transformations that helps |
|||
greatly in 3D graphics processing.</p> |
|||
<p><b>Tutorial compatible with PSn00bSDK:</b>Yes</p> |
|||
|
|||
<h2>Tutorial Index</h2> |
|||
<ul> |
|||
<li><a href="#operation">Theory of Operation</a></li> |
|||
<li><a href="#ordertable">Ordering Tables</a></li> |
|||
<li><a href="#primitives">Primitive Packets</a></li> |
|||
<li><a href="#primprep">Preparing a Primitive</a></li> |
|||
<li><a href="#primbuff">Primitive Buffers</a></li> |
|||
<li><a href="#otsort">Sorting a Primitive to an Ordering Table</a></li> |
|||
<li><a href="#otdraw">Drawing an Ordering Table</a></li> |
|||
<li><a href="#doublebuff">Double Ordering Tables/Primitive Buffers</a></li> |
|||
<li><a href="#samplecode">Sample Code</a></li> |
|||
<li><a href="#conclusion">Conclusion</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="operation">Theory of Operation</h2> |
|||
<p>The PS1 GPU draws graphics by means of primitive packets, which are |
|||
essentially messages that command the GPU to draw a specified primitive |
|||
in a specified color to specified screen coordinates to name a few.</p> |
|||
<p>Drawing packets are normally sent to the GPU by an ordering table, |
|||
which is essentially an array of pointers that form a chain. Primitive |
|||
packets are normally linked to the ordering table to draw them.</p> |
|||
|
|||
<h2 id="ordertable">Ordering Tables</h2> |
|||
<p>An ordering table is an array of elements of pointers that point from |
|||
one element to another, the ordering table usually ends with an array element |
|||
with the value of 0xFFFFFFFF which is used as a terminator value for ordering |
|||
table processing. An ordering table is normally created using <b>ClearOTagR()</b> |
|||
on an array of 32-bit ints.</p> |
|||
<p>The following figure visually describes the general structure of an ordering table.</p> |
|||
<img src="Chapter%201.2%20Drawing%20Graphics_files/ordertable.svg"> |
|||
<p>Adding primitives to an ordering table is normally achieved using |
|||
<b>addPrim()/AddPrim()</b> functions. <b>DrawOTag()</b> is used to begin |
|||
processing of an ordering table.</p> |
|||
<p>The type of ordering table shown above is called a reverse ordering table |
|||
because the chain starts at the end of the array and ends at the beginning of |
|||
the array. This type of ordering table is most commonly used as the reverse |
|||
order allows for depth ordering of polygons which is essential for 3D graphics. |
|||
Use <b>ClearOTag()</b> if you wish to use a non-reverse ordering table but the |
|||
initialization speed won't be as fast as <b>ClearOTagR()</b> for larger tables |
|||
as <b>ClearOTagR()</b> is DMA accelerated, but it can only generate reverse |
|||
ordering tables.</p> |
|||
<p>For simplicity, a global ordering table array of 8 elements should suffice |
|||
for this tutorial.</p> |
|||
<pre>int ot[2][8]; |
|||
</pre> |
|||
<p>The reason two arrays of <h>ot</h> are defined is for double buffered |
|||
rendering reasons, which will be explained later in this tutorial.</p> |
|||
|
|||
<h2 id="primitives">Primitive Packets</h2> |
|||
<p>Primitive packets are more or less commands that instruct the GPU to draw |
|||
a specified primitive to specified coordinates of the drawing area carried by |
|||
the packet. Primitive packets are always aligned 4-byte aligned.</p> |
|||
<p>The following illustrates the typical structure of a primitive packet |
|||
(the packet represents a <b>SPRT</b> primitive):</p> |
|||
<img src="Chapter%201.2%20Drawing%20Graphics_files/primstruct.svg"> |
|||
<p>C implementation of the above structure</p> |
|||
<pre>typedef struct { |
|||
unsigned int tag; // First 24 bits are address, last 8 bits are length |
|||
unsigned char r0,g0,b0,code; // RGB color and primitive code |
|||
short x0,y0; // X,Y coordinates of sprite |
|||
unsigned char u0,v0; // U,V texture coordinates of sprite |
|||
unsigned short clut; // Texture CLUT |
|||
unsigned short w,h; // Sprite width and height |
|||
} SPRT; |
|||
</pre> |
|||
<p>The number of parameter words of a primitive packet varies on the primitive |
|||
command. Simpler commands such as a fixed sized, solid color sprite is only 3 |
|||
words long whereas a shaded, textured 4-point polygon is 13 words long, the |
|||
length of the primitive in words is specified to the <i>Len</i> field minus the |
|||
tag word. The <i>Next Pointer</i> field is an address to the next primitive or |
|||
return pointer to an ordering table it was sorted to.</p> |
|||
<p>A word in this context is a 4 byte integer.</p> |
|||
<p>Primitives are normally defined using primitive structures and macros |
|||
defined in libgpu.h, or psxgpu.h in PSn00bSDK.</p> |
|||
|
|||
<h2 id="primprep">Preparing a Primitive</h2> |
|||
<p>Primitive packets are normally prepared using primitive structures and |
|||
macros. A solid color rectangular sprite (<b>TILE</b>) will be used for this |
|||
tutorial.</p> |
|||
<p>Primitive preparation is as follows.</p> |
|||
<pre>TILE tile; // Primitive structure |
|||
|
|||
setTile(&tile;); // Initialize the primitive (very important) |
|||
setXY0(&tile;, 32, 32); // Set primitive (x,y) position |
|||
setWH(&tile;, 64, 64); // Set primitive size |
|||
setRGB0(&tile;, 255, 255, 0); // Set color yellow |
|||
</pre> |
|||
<p>The <b>setTile()</b> macro simply fills in the appropriate values to the tag |
|||
length and primitive code fields to the specified primitive. These values are |
|||
mandatory and must be correct, otherwise the GPU will lock up. Always use the |
|||
appropriate initializer macro for a primitive.</p> |
|||
<p>The <b>setXY0()</b>, <b>setWH()</b> and <b>setRGB0()</b> macros sets the |
|||
(x,y) coordinates, size and color of the primitive respectively. While the |
|||
fields of a primitive can be set directly via struct elements of the |
|||
primitive, using macros helps make the code looking tidy.</p> |
|||
<p>Normally, primitive packets are defined to a primitive buffer.</p> |
|||
|
|||
<h2 id="primbuff">Primitive Buffers</h2> |
|||
<p>A primitive buffer is simply a global array of char elements used as a |
|||
buffer to define primitive packets to. It is also a lot less wasteful than |
|||
defining multiple arrays for different primitive types as all primitive types |
|||
can be defined in just a single global buffer.</p> |
|||
<p>The reason it is recommended that primitive packets must be defined in a |
|||
global buffer is because the primitives must exist in memory until the GPU |
|||
gets around to processing it. If you were to define primitives as a local |
|||
variable in a function and register it to an ordering table, that primitive |
|||
has most likely been overwritten by other things (since locals are generally |
|||
temporary variables), resulting in a corrupted ordering table which would |
|||
result to a GPU lock up or crash.</p> |
|||
<p>A primitive buffer can be defined as such, 32KB buffer for primitives |
|||
should be plenty.</p> |
|||
<pre>char primbuff[2][32768]; |
|||
char *nextpri; |
|||
</pre> |
|||
<p>The <h>nextpri</h> variable will be used to keep track where the next |
|||
primitive should be written to. Therefore, this variable must be set to |
|||
the first primitive buffer and reset in your display function.</p> |
|||
<p>To prepare a primitive to the primitive buffer, simply cast the |
|||
nextpri pointer into a primitive pointer.</p> |
|||
<pre>TILE *tile; // Primitive pointer |
|||
|
|||
tile = (TILE*)nextpri; // Cast hext primitive |
|||
|
|||
setTile(tile); // Initialize the primitive (very important) |
|||
setXY0(tile, 32, 32); // Set primitive (x,y) position |
|||
setWH(tile, 64, 64); // Set primitive size |
|||
setRGB0(tile, 255, 255, 0); // Set color yellow |
|||
</pre> |
|||
<p>After registering the primitive to the ordering table, you'll want to |
|||
advance the <i>nextpri</i> pointer for another primitive to be written to.</p> |
|||
<pre>nextpri += sizeof(TILE); |
|||
</pre> |
|||
<p>It is very important to advance this pointer, otherwise previously defined |
|||
packets would get overwritten, corrupting the primitive buffer.</p> |
|||
|
|||
<h2 id="otsort">Sorting a Primitive to an Ordering Table</h2> |
|||
<p>The term 'sorting' in the context of PS1 graphics programming refers to |
|||
linking a primitive to an ordering table element. Its often called sorting |
|||
because an ordering table is also used to control the order of which |
|||
primitives are drawn. In a reverse ordering table (initialized using |
|||
ClearOTagR()) a primitive sorted highest will be drawn first and primitives |
|||
sorted lowest will be drawn last, which would make a lot of sense in 3D |
|||
graphics.</p> |
|||
<p>Sorting a primitive to an ordering table is achieved using the |
|||
<b>addPrim()</b> macro.</p> |
|||
<pre>addPrim(ot[db], tile); |
|||
</pre> |
|||
<p>There's also a function version called <b>AddPrim()</b> but the macro version |
|||
would be faster in the long run, mainly because code jumps are kept a minimum when |
|||
using macros.</p> |
|||
<p>Taking the code snippet earlier, this is the process of how to create and sort |
|||
a primitive to be drawn.</p> |
|||
<pre>tile = (TILE*)nextpri; // Cast next primitive |
|||
|
|||
setTile(tile); // Initialize the primitive (very important) |
|||
setXY0(tile, 32, 32); // Set primitive (x,y) position |
|||
setWH(tile, 64, 64); // Set primitive size |
|||
setRGB0(tile, 255, 255, 0); // Set color yellow |
|||
|
|||
addPrim(ot[db], tile); // Add primitive to the ordering table |
|||
|
|||
nextpri += sizeof(TILE); // Advance the next primitive pointer |
|||
</pre> |
|||
<p>Primitives need to be sorted to an ordering table for the GPU to process it. |
|||
To sort the primitive to a higher ordering table element, simply use (+) to |
|||
increment the ordering table address. But don't increment by a value that |
|||
will exceed the length of your ordering table, or that will result to memory |
|||
overflow corruption.</p> |
|||
<p>Sorting a primitive to an ordering table links the specified primitive into |
|||
the chain, so it gets processed when the OT is proceessed by the GPU. The |
|||
following figure visually describes the result of sorting a primitive to ordering |
|||
table element 4.</p> |
|||
<img src="Chapter%201.2%20Drawing%20Graphics_files/ordertable-primitive.svg"> |
|||
<p>A very common misconception among many PS1 homebrew programmers is they believe |
|||
only a single primitive can be sorted to an ordering table element. This is |
|||
absolutely untrue because sorting a primitive to an element that has a primitive |
|||
already linked to it will only add further to the chain, not replace the previous |
|||
element.</p> |
|||
<img src="Chapter%201.2%20Drawing%20Graphics_files/ordertable-multiprims.svg"> |
|||
<p>You can sort any number of primitives to a single ordering table, so an ordering |
|||
table of 4 to 8 elements should be sufficient for 2D projects. But remember that the |
|||
newest primitive sorted will be the first to be processed, as shown in the figure |
|||
earlier.</p> |
|||
|
|||
<h2 id="otdraw">Drawing an Ordering Table</h2> |
|||
<p>Ordering table processing is done using the <b>DrawOTag()</b> function. |
|||
<b>DrawOTag()</b> starts a DMA transfer process of the specified ordering |
|||
table for the GPU to process. This is the most recommended method of |
|||
processing ordering tables as this is the fastest way to deliver graphics |
|||
primitives to the GPU.</p> |
|||
<p>Since this tutorial demonstrates the use of a reverse ordering table, the |
|||
last element of the ordering table must be specified to <b>DrawOTag()</b>, as |
|||
the chain starts at the last element and ends at the first.</p> |
|||
<pre>DrawOTag(ot[db]+31); |
|||
</pre> |
|||
<p>The transfer operation is asynchronous so the function returns very |
|||
quickly. It is recommended to wait for the transfer and the GPU to finish |
|||
processing which is achieved using <b>DrawSync()</b> before processing another |
|||
ordering table.</p> |
|||
|
|||
<h2 id="doublebuff">Double Ordering Tables/Primitive Buffers</h2> |
|||
<p>You may have noticed by now that ordering tables and primitive buffers are |
|||
defined in pairs. This is so that a commonly used optimization trick can be |
|||
achieved and is another form of double buffering. Because the CPU can continue |
|||
running while the GPU is busy processing graphics, you can utilize this to |
|||
continue processing graphics primitives for drawing the next frame while the |
|||
GPU is drawing. The following figure visually describes the performance |
|||
difference.</p> |
|||
<img src="Chapter%201.2%20Drawing%20Graphics_files/ordertable-buffercompare.svg"> |
|||
<p>Having double buffers essentially minimizes keeping the GPU idle which |
|||
comes off as being most efficient, as having single buffers would prevent |
|||
you from preparing primitives for the next frame which results to leaving |
|||
the GPU in an idle state. While this may not be apparent in small programs, |
|||
it will be once you start pushing the GPU with thousands of primitives.</p> |
|||
|
|||
<h2 id="samplecode">Sample Code</h2> |
|||
<p>The sample code works off of the one from the previous example, but with |
|||
graphics drawing code implemented.</p> |
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <libetc.h> // Includes some functions that controls the display |
|||
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <libgpu.h> // GPU library header |
|||
|
|||
#define OTLEN 8 // Ordering table length (recommended to set as a define |
|||
// so it can be changed easily) |
|||
|
|||
DISPENV disp[2]; |
|||
DRAWENV draw[2]; |
|||
int db = 0; |
|||
|
|||
u_long ot[2][OTLEN]; // Ordering table length |
|||
char pribuff[2][32768]; // Primitive buffer |
|||
char *nextpri; // Next primitive pointer |
|||
|
|||
void display() { |
|||
|
|||
DrawSync(0); // Wait for any graphics processing to finish |
|||
|
|||
VSync(0); // Wait for vertical retrace |
|||
|
|||
PutDispEnv(&disp;[db]); // Apply the DISPENV/DRAWENVs |
|||
PutDrawEnv(&draw;[db]); |
|||
|
|||
SetDispMask(1); // Enable the display |
|||
|
|||
DrawOTag(ot[db]+OTLEN-1); // Draw the ordering table |
|||
|
|||
db = !db; // Swap buffers on every pass (alternates between 1 and 0) |
|||
nextpri = pribuff[db]; // Reset next primitive pointer |
|||
|
|||
} |
|||
|
|||
int main() { |
|||
|
|||
TILE *tile; // Primitive pointer |
|||
|
|||
// Reset graphics |
|||
ResetGraph(0); |
|||
|
|||
// First buffer |
|||
SetDefDispEnv(&disp;[0], 0, 0, 320, 240); |
|||
SetDefDrawEnv(&draw;[0], 0, 240, 320, 240); |
|||
// Second buffer |
|||
SetDefDispEnv(&disp;[1], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw;[1], 0, 0, 320, 240); |
|||
|
|||
draw[0].isbg = 1; // Enable clear |
|||
setRGB0(&draw;[0], 63, 0, 127); // Set clear color (dark purple) |
|||
draw[1].isbg = 1; |
|||
setRGB0(&draw;[1], 63, 0, 127); |
|||
|
|||
nextpri = pribuff[0]; // Set initial primitive pointer address |
|||
|
|||
while(1) { |
|||
|
|||
ClearOTagR(ot[db], OTLEN); // Clear ordering table |
|||
|
|||
|
|||
tile = (TILE*)nextpri; // Cast next primitive |
|||
|
|||
setTile(tile); // Initialize the primitive (very important) |
|||
setXY0(tile, 32, 32); // Set primitive (x,y) position |
|||
setWH(tile, 64, 64); // Set primitive size |
|||
setRGB0(tile, 255, 255, 0); // Set color yellow |
|||
addPrim(ot[db], tile); // Add primitive to the ordering table |
|||
|
|||
nextpri += sizeof(TILE); // Advance the next primitive pointer |
|||
|
|||
|
|||
// Update the display |
|||
display(); |
|||
|
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
<p>Compile and run the program and you should get a yellow square. |
|||
Your very first graphic done with the GPU!</p> |
|||
<img src="Chapter%201.2%20Drawing%20Graphics_files/2-graphics.png"> |
|||
|
|||
<h2 id="conclusion">Conclusion</h2> |
|||
<p>This concludes Chapter 1.2. of Lameguy64's PSX Tutorial series. |
|||
You should know more about drawing graphics on the PS1 after reading |
|||
through this chapter.</p> |
|||
<p>A few things you may want to experiment with yourself for further |
|||
learning:</p> |
|||
<ul> |
|||
<li>Play around with the values specified in <b>setXY0()</b>, <b>setRGB0()</b> |
|||
and <b>setWH()</b> to change the position, color and size of the sprite |
|||
respectively.</li> |
|||
<li>Try drawing more sprites by repeating the primitive creation process. |
|||
Make sure the <h>nextpri</h> and <h>tile</h> pointers have been advanced before |
|||
creating a new primitive.</li> |
|||
<li>You can advance the primitive pointer with <h>tile++;</h>, and set the |
|||
updated address to <h>nextpri</h> by converting types back |
|||
(<h>nextpri = (char*)tile;</h>)</li> |
|||
<li>Try making the yellow square bounce around the screen, by defining |
|||
two variables for (x,y) coordinates and two more for the direction flags, |
|||
and write some logic that makes the (x,y) coordinates move and bounce |
|||
around the screen.</li> |
|||
</ul> |
|||
<p>The next tutorial will cover how to convert and upload texture data, as |
|||
well as drawing said textures with sprite and polygon primitives.</p> |
|||
<hr> |
|||
|
|||
<table class="footer-table" width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left"><a href="http://web.archive.org/web/20220827033534/http://lameguy64.net/tutorials/pstutorials/chapter1/1-display.html">Previous</a></td> |
|||
<td width="20%" align="center"><a href="http://web.archive.org/web/20220827033534/http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"><a href="http://web.archive.org/web/20220827033534/http://lameguy64.net/tutorials/pstutorials/chapter1/3-textures.html">Next</a></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
|
|||
|
|||
</body></html> |
|||
<!-- |
|||
FILE ARCHIVED ON 03:35:34 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:40:29 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
--> |
|||
<!-- |
|||
playback timings (ms): |
|||
captures_list: 241.637 |
|||
exclusion.robots: 0.473 |
|||
exclusion.robots.policy: 0.464 |
|||
RedisCDXSource: 14.466 |
|||
esindex: 0.01 |
|||
LoadShardBlock: 195.528 (3) |
|||
PetaboxLoader3.datanode: 171.89 (4) |
|||
CDXLines.iter: 27.223 (3) |
|||
load_resource: 118.452 |
|||
PetaboxLoader3.resolve: 85.381 |
|||
--> |
|||
@ -0,0 +1,474 @@ |
|||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3.0
|
|||
/* eslint-disable no-var, semi, prefer-arrow-callback, prefer-template */ |
|||
|
|||
/** |
|||
* Collection of methods for sending analytics events to Archive.org's analytics server. |
|||
* |
|||
* These events are used for internal stats and sent (in anonymized form) to Google Analytics. |
|||
* |
|||
* @see analytics.md |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
window.archive_analytics = (function defineArchiveAnalytics() { |
|||
// keep orignal Date object so as not to be affected by wayback's
|
|||
// hijacking global Date object
|
|||
var Date = window.Date; |
|||
var ARCHIVE_ANALYTICS_VERSION = 2; |
|||
var DEFAULT_SERVICE = 'ao_2'; |
|||
var NO_SAMPLING_SERVICE = 'ao_no_sampling'; // sends every event instead of a percentage
|
|||
|
|||
var startTime = new Date(); |
|||
|
|||
/** |
|||
* @return {Boolean} |
|||
*/ |
|||
function isPerformanceTimingApiSupported() { |
|||
return 'performance' in window && 'timing' in window.performance; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the browser starting to parse the DOM and |
|||
* the current time. |
|||
* |
|||
* Uses the Performance API or a fallback value if it's not available. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number} |
|||
*/ |
|||
function getLoadTime() { |
|||
var start; |
|||
|
|||
if (isPerformanceTimingApiSupported()) |
|||
start = window.performance.timing.domLoading; |
|||
else |
|||
start = startTime.getTime(); |
|||
|
|||
return new Date().getTime() - start; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the user navigating to the page and |
|||
* the current time. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number|null} null if the browser doesn't support the Performance API |
|||
*/ |
|||
function getNavToDoneTime() { |
|||
if (!isPerformanceTimingApiSupported()) |
|||
return null; |
|||
|
|||
return new Date().getTime() - window.performance.timing.navigationStart; |
|||
} |
|||
|
|||
/** |
|||
* Performs an arithmetic calculation on a string with a number and unit, while maintaining |
|||
* the unit. |
|||
* |
|||
* @param {String} original value to modify, with a unit |
|||
* @param {Function} doOperation accepts one Number parameter, returns a Number |
|||
* @returns {String} |
|||
*/ |
|||
function computeWithUnit(original, doOperation) { |
|||
var number = parseFloat(original, 10); |
|||
var unit = original.replace(/(\d*\.\d+)|\d+/, ''); |
|||
|
|||
return doOperation(number) + unit; |
|||
} |
|||
|
|||
/** |
|||
* Computes the default font size of the browser. |
|||
* |
|||
* @returns {String|null} computed font-size with units (typically pixels), null if it cannot be computed |
|||
*/ |
|||
function getDefaultFontSize() { |
|||
var fontSizeStr; |
|||
|
|||
if (!('getComputedStyle' in window)) |
|||
return null; |
|||
|
|||
var style = window.getComputedStyle(document.documentElement); |
|||
if (!style) |
|||
return null; |
|||
|
|||
fontSizeStr = style.fontSize; |
|||
|
|||
// Don't modify the value if tracking book reader.
|
|||
if (document.querySelector('#BookReader')) |
|||
return fontSizeStr; |
|||
|
|||
return computeWithUnit(fontSizeStr, function reverseBootstrapFontSize(number) { |
|||
// Undo the 62.5% size applied in the Bootstrap CSS.
|
|||
return number * 1.6; |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Get the URL parameters for a given Location |
|||
* @param {Location} |
|||
* @return {Object} The URL parameters |
|||
*/ |
|||
function getParams(location) { |
|||
if (!location) location = window.location; |
|||
var vars; |
|||
var i; |
|||
var pair; |
|||
var params = {}; |
|||
var query = location.search; |
|||
if (!query) return params; |
|||
vars = query.substring(1).split('&'); |
|||
for (i = 0; i < vars.length; i++) { |
|||
pair = vars[i].split('='); |
|||
params[pair[0]] = decodeURIComponent(pair[1]); |
|||
} |
|||
return params; |
|||
} |
|||
|
|||
function getMetaProp(name) { |
|||
var metaTag = document.querySelector('meta[property=' + name + ']'); |
|||
return metaTag ? metaTag.getAttribute('content') || null : null; |
|||
} |
|||
|
|||
var ArchiveAnalytics = { |
|||
/** |
|||
* @type {String|null} |
|||
*/ |
|||
service: getMetaProp('service'), |
|||
mediaType: getMetaProp('mediatype'), |
|||
primaryCollection: getMetaProp('primary_collection'), |
|||
|
|||
/** |
|||
* Key-value pairs to send in pageviews (you can read this after a pageview to see what was |
|||
* sent). |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
values: {}, |
|||
|
|||
/** |
|||
* Sends an analytics ping, preferably using navigator.sendBeacon() |
|||
* @param {Object} values |
|||
* @param {Function} [onload_callback] (deprecated) callback to invoke once ping to analytics server is done |
|||
* @param {Boolean} [augment_for_ao_site] (deprecated) if true, add some archive.org site-specific values |
|||
*/ |
|||
send_ping: function send_ping(values, onload_callback, augment_for_ao_site) { |
|||
if (typeof window.navigator !== 'undefined' && typeof window.navigator.sendBeacon !== 'undefined') |
|||
this.send_ping_via_beacon(values); |
|||
else |
|||
this.send_ping_via_image(values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Beacon API |
|||
* NOTE: Assumes window.navigator.sendBeacon exists |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_beacon: function send_ping_via_beacon(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
window.navigator.sendBeacon(url); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Image object |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_image: function send_ping_via_image(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
var loadtime_img = new Image(1, 1); |
|||
loadtime_img.src = url; |
|||
loadtime_img.alt = ''; |
|||
}, |
|||
|
|||
/** |
|||
* Construct complete tracking URL containing payload |
|||
* @param {Object} params Tracking parameters to pass |
|||
* @return {String} URL to use for tracking call |
|||
*/ |
|||
generate_tracking_url: function generate_tracking_url(params) { |
|||
var baseUrl = '//analytics.archive.org/0.gif'; |
|||
var keys; |
|||
var outputParams = params; |
|||
var outputParamsArray = []; |
|||
|
|||
outputParams.service = outputParams.service || this.service || DEFAULT_SERVICE; |
|||
|
|||
// Build array of querystring parameters
|
|||
keys = Object.keys(outputParams); |
|||
keys.forEach(function keyIteration(key) { |
|||
outputParamsArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(outputParams[key])); |
|||
}); |
|||
outputParamsArray.push('version=' + ARCHIVE_ANALYTICS_VERSION); |
|||
outputParamsArray.push('count=' + (keys.length + 2)); // Include `version` and `count` in count
|
|||
|
|||
return baseUrl + '?' + outputParamsArray.join('&'); |
|||
}, |
|||
|
|||
/** |
|||
* @param {int} page Page number |
|||
*/ |
|||
send_scroll_fetch_event: function send_scroll_fetch_event(page) { |
|||
var additionalValues = { ev: page }; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
send_scroll_fetch_base_event: function send_scroll_fetch_base_event() { |
|||
var additionalValues = {}; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch_base', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} [options] |
|||
* @param {String} [options.mediaType] |
|||
* @param {String} [options.mediaLanguage] |
|||
* @param {String} [options.page] The path portion of the page URL |
|||
*/ |
|||
send_pageview: function send_pageview(options) { |
|||
var settings = options || {}; |
|||
|
|||
var defaultFontSize; |
|||
var loadTime = getLoadTime(); |
|||
var mediaType = settings.mediaType; |
|||
var primaryCollection = settings.primaryCollection; |
|||
var page = settings.page; |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
|
|||
/** |
|||
* @return {String} |
|||
*/ |
|||
function get_locale() { |
|||
if (navigator) { |
|||
if (navigator.language) |
|||
return navigator.language; |
|||
|
|||
else if (navigator.browserLanguage) |
|||
return navigator.browserLanguage; |
|||
|
|||
else if (navigator.systemLanguage) |
|||
return navigator.systemLanguage; |
|||
|
|||
else if (navigator.userLanguage) |
|||
return navigator.userLanguage; |
|||
} |
|||
return ''; |
|||
} |
|||
|
|||
defaultFontSize = getDefaultFontSize(); |
|||
|
|||
// Set field values
|
|||
this.values.kind = 'pageview'; |
|||
this.values.timediff = (new Date().getTimezoneOffset()/60)*(-1); // *timezone* diff from UTC
|
|||
this.values.locale = get_locale(); |
|||
this.values.referrer = (document.referrer == '' ? '-' : document.referrer); |
|||
|
|||
if (loadTime) |
|||
this.values.loadtime = loadTime; |
|||
|
|||
if (navToDoneTime) |
|||
this.values.nav_to_done_ms = navToDoneTime; |
|||
|
|||
if (settings.trackingId) { |
|||
this.values.ga_tid = settings.trackingId; |
|||
} |
|||
|
|||
/* START CUSTOM DIMENSIONS */ |
|||
if (defaultFontSize) |
|||
this.values.ga_cd1 = defaultFontSize; |
|||
|
|||
if ('devicePixelRatio' in window) |
|||
this.values.ga_cd2 = window.devicePixelRatio; |
|||
|
|||
if (mediaType) |
|||
this.values.ga_cd3 = mediaType; |
|||
|
|||
if (settings.mediaLanguage) { |
|||
this.values.ga_cd4 = settings.mediaLanguage; |
|||
} |
|||
|
|||
if (primaryCollection) { |
|||
this.values.ga_cd5 = primaryCollection; |
|||
} |
|||
/* END CUSTOM DIMENSIONS */ |
|||
|
|||
if (page) |
|||
this.values.page = page; |
|||
|
|||
this.send_ping(this.values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a tracking "Event". |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event: function send_event( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
if (!label) label = window.location.pathname; |
|||
if (!additionalEventParams) additionalEventParams = {}; |
|||
if (additionalEventParams.mediaLanguage) { |
|||
additionalEventParams.ga_cd4 = additionalEventParams.mediaLanguage; |
|||
delete additionalEventParams.mediaLanguage; |
|||
} |
|||
var eventParams = Object.assign( |
|||
{ |
|||
kind: 'event', |
|||
ec: category, |
|||
ea: action, |
|||
el: label, |
|||
cache_bust: Math.random(), |
|||
}, |
|||
additionalEventParams |
|||
); |
|||
this.send_ping(eventParams); |
|||
}, |
|||
|
|||
/** |
|||
* Sends every event instead of a small percentage. |
|||
* |
|||
* Use this sparingly as it can generate a lot of events. |
|||
* |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event_no_sampling: function send_event_no_sampling( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
var extraParams = additionalEventParams || {}; |
|||
extraParams.service = NO_SAMPLING_SERVICE; |
|||
this.send_event(category, action, label, extraParams); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} options see this.send_pageview options |
|||
*/ |
|||
send_pageview_on_load: function send_pageview_on_load(options) { |
|||
var self = this; |
|||
window.addEventListener('load', function send_pageview_with_options() { |
|||
self.send_pageview(options); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* Handles tracking events passed in URL. |
|||
* Assumes category and action values are separated by a "|" character. |
|||
* NOTE: Uses the unsampled analytics property. Watch out for future high click links! |
|||
* @param {Location} |
|||
*/ |
|||
process_url_events: function process_url_events(location) { |
|||
var eventValues; |
|||
var actionValue; |
|||
var eventValue = getParams(location).iax; |
|||
if (!eventValue) return; |
|||
eventValues = eventValue.split('|'); |
|||
actionValue = eventValues.length >= 1 ? eventValues[1] : ''; |
|||
this.send_event_no_sampling( |
|||
eventValues[0], |
|||
actionValue, |
|||
window.location.pathname |
|||
); |
|||
}, |
|||
|
|||
/** |
|||
* Attaches handlers for event tracking. |
|||
* |
|||
* To enable click tracking for a link, add a `data-event-click-tracking` |
|||
* attribute containing the Google Analytics Event Category and Action, separated |
|||
* by a vertical pipe (|). |
|||
* e.g. `<a href="foobar" data-event-click-tracking="TopNav|FooBar">` |
|||
* |
|||
* To enable form submit tracking, add a `data-event-form-tracking` attribute |
|||
* to the `form` tag. |
|||
* e.g. `<form data-event-form-tracking="TopNav|SearchForm" method="GET">` |
|||
* |
|||
* Additional tracking options can be added via a `data-event-tracking-options` |
|||
* parameter. This parameter, if included, should be a JSON string of the parameters. |
|||
* Valid parameters are: |
|||
* - service {string}: Corresponds to the Google Analytics property data values flow into |
|||
*/ |
|||
set_up_event_tracking: function set_up_event_tracking() { |
|||
var self = this; |
|||
var clickTrackingAttributeName = 'event-click-tracking'; |
|||
var formTrackingAttributeName = 'event-form-tracking'; |
|||
var trackingOptionsAttributeName = 'event-tracking-options'; |
|||
|
|||
function handleAction(event, attributeName) { |
|||
var selector = '[data-' + attributeName + ']'; |
|||
var eventTarget = event.target; |
|||
if (!eventTarget) return; |
|||
var target = eventTarget.closest(selector); |
|||
if (!target) return; |
|||
var categoryAction; |
|||
var categoryActionParts; |
|||
var options; |
|||
categoryAction = target.dataset[toCamelCase(attributeName)]; |
|||
if (!categoryAction) return; |
|||
categoryActionParts = categoryAction.split('|'); |
|||
options = target.dataset[toCamelCase(trackingOptionsAttributeName)]; |
|||
options = options ? JSON.parse(options) : {}; |
|||
self.send_event( |
|||
categoryActionParts[0], |
|||
categoryActionParts[1], |
|||
categoryActionParts[2] || window.location.pathname, |
|||
options.service ? { service: options.service } : {} |
|||
); |
|||
} |
|||
|
|||
function toCamelCase(str) { |
|||
return str.replace(/\W+(.)/g, function (match, chr) { |
|||
return chr.toUpperCase(); |
|||
}); |
|||
}; |
|||
|
|||
document.addEventListener('click', function(e) { |
|||
handleAction(e, clickTrackingAttributeName); |
|||
}); |
|||
|
|||
document.addEventListener('submit', function(e) { |
|||
handleAction(e, formTrackingAttributeName); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* @returns {Object[]} |
|||
*/ |
|||
get_data_packets: function get_data_packets() { |
|||
return [this.values]; |
|||
}, |
|||
|
|||
/** |
|||
* Creates a tracking image for tracking JS compatibility. |
|||
* |
|||
* @param {string} type The type value for track_js_case in query params for 0.gif |
|||
*/ |
|||
create_tracking_image: function create_tracking_image(type) { |
|||
this.send_ping_via_image({ |
|||
cache_bust: Math.random(), |
|||
kind: 'track_js', |
|||
track_js_case: type, |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
return ArchiveAnalytics; |
|||
}()); |
|||
// @license-end
|
|||
@ -0,0 +1,500 @@ |
|||
@import 'record.css'; /* for SPN1 */ |
|||
|
|||
#wm-ipp-base { |
|||
height:65px;/* initial height just in case js code fails */ |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
background:none transparent; |
|||
} |
|||
#wm-ipp { |
|||
z-index: 2147483647; |
|||
} |
|||
#wm-ipp, #wm-ipp * { |
|||
font-family:Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size:12px; |
|||
line-height:1.2; |
|||
letter-spacing:0; |
|||
width:auto; |
|||
height:auto; |
|||
max-width:none; |
|||
max-height:none; |
|||
min-width:0 !important; |
|||
min-height:0; |
|||
outline:none; |
|||
float:none; |
|||
text-align:left; |
|||
border:none; |
|||
color: #000; |
|||
text-indent: 0; |
|||
position: initial; |
|||
background: none; |
|||
} |
|||
#wm-ipp div, #wm-ipp canvas { |
|||
display: block; |
|||
} |
|||
#wm-ipp div, #wm-ipp tr, #wm-ipp td, #wm-ipp a, #wm-ipp form { |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
border-radius:0; |
|||
background-color:transparent; |
|||
background-image:none; |
|||
/*z-index:2147483640;*/ |
|||
height:auto; |
|||
} |
|||
#wm-ipp table { |
|||
border:none; |
|||
border-collapse:collapse; |
|||
margin:0; |
|||
padding:0; |
|||
width:auto; |
|||
font-size:inherit; |
|||
} |
|||
#wm-ipp form input { |
|||
padding:1px !important; |
|||
height:auto; |
|||
display:inline; |
|||
margin:0; |
|||
color: #000; |
|||
background: none #fff; |
|||
border: 1px solid #666; |
|||
} |
|||
#wm-ipp form input[type=submit] { |
|||
padding:0 8px !important; |
|||
margin:1px 0 1px 5px !important; |
|||
width:auto !important; |
|||
border: 1px solid #000 !important; |
|||
background: #fff !important; |
|||
color: #000 !important; |
|||
} |
|||
#wm-ipp a { |
|||
display: inline; |
|||
} |
|||
#wm-ipp a:hover{ |
|||
text-decoration:underline; |
|||
} |
|||
#wm-ipp a.wm-btn:hover { |
|||
text-decoration:none; |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp a.wm-btn:hover span { |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp #wm-ipp-inside { |
|||
margin: 0 6px; |
|||
border:5px solid #000; |
|||
border-top:none; |
|||
background-color:rgba(255,255,255,0.9); |
|||
-moz-box-shadow:1px 1px 4px #333; |
|||
-webkit-box-shadow:1px 1px 4px #333; |
|||
box-shadow:1px 1px 4px #333; |
|||
border-radius:0 0 8px 8px; |
|||
} |
|||
/* selectors are intentionally verbose to ensure priority */ |
|||
#wm-ipp #wm-logo { |
|||
padding:0 10px; |
|||
vertical-align:middle; |
|||
min-width:100px; |
|||
flex: 0 0 100px; |
|||
} |
|||
#wm-ipp .c { |
|||
padding-left: 4px; |
|||
} |
|||
#wm-ipp .c .u { |
|||
margin-top: 4px !important; |
|||
} |
|||
#wm-ipp .n { |
|||
padding:0 0 0 5px !important; |
|||
vertical-align: bottom; |
|||
} |
|||
#wm-ipp .n a { |
|||
text-decoration:none; |
|||
color:#33f; |
|||
font-weight:bold; |
|||
} |
|||
#wm-ipp .n .b { |
|||
padding:0 6px 0 0 !important; |
|||
text-align:right !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n .y .b { |
|||
padding:0 6px 2px 0 !important; |
|||
} |
|||
#wm-ipp .n .c { |
|||
background:#000; |
|||
color:#ff0; |
|||
font-weight:bold; |
|||
padding:0 !important; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp.hi .n td.c { |
|||
color:#ec008c; |
|||
} |
|||
#wm-ipp .n td.f { |
|||
padding:0 0 0 6px !important; |
|||
text-align:left !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n tr.m td { |
|||
text-transform:uppercase; |
|||
white-space:nowrap; |
|||
padding:2px 0; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 0 0 !important; |
|||
vertical-align:bottom; |
|||
} |
|||
#wm-ipp #wm-nav-captures { |
|||
white-space: nowrap; |
|||
} |
|||
#wm-ipp .c .s a.t { |
|||
color:#33f; |
|||
font-weight:bold; |
|||
line-height: 1.8; |
|||
} |
|||
#wm-ipp .c .s div.r { |
|||
color: #666; |
|||
font-size:9px; |
|||
white-space:nowrap; |
|||
} |
|||
#wm-ipp .c .k { |
|||
padding-bottom:1px; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayMonthEl { |
|||
padding: 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayYearEl { |
|||
padding: 0 0 2px 0 !important; |
|||
} |
|||
|
|||
div#wm-ipp-sparkline { |
|||
position:relative;/* for positioning markers */ |
|||
white-space:nowrap; |
|||
background-color:#fff; |
|||
cursor:pointer; |
|||
line-height:0.9; |
|||
} |
|||
#sparklineImgId, #wm-sparkline-canvas { |
|||
position:relative; |
|||
z-index:9012; |
|||
max-width:none; |
|||
} |
|||
#wm-ipp-sparkline div.yt { |
|||
position:absolute; |
|||
z-index:9010 !important; |
|||
background-color:#ff0 !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp-sparkline div.mt { |
|||
position:absolute; |
|||
z-index:9013 !important; |
|||
background-color:#ec008c !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp .r { |
|||
margin-left: 4px; |
|||
} |
|||
#wm-ipp .r a { |
|||
color:#33f; |
|||
border:none; |
|||
position:relative; |
|||
background-color:transparent; |
|||
background-repeat:no-repeat !important; |
|||
background-position:100% 100% !important; |
|||
text-decoration: none; |
|||
} |
|||
#wm-ipp #wm-capinfo { |
|||
/* prevents notice div background from sticking into round corners of |
|||
#wm-ipp-inside */ |
|||
border-radius: 0 0 4px 4px; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo { |
|||
display:block; |
|||
float:left; |
|||
margin-right:3px; |
|||
width:90px; |
|||
min-height:90px; |
|||
max-height: 290px; |
|||
border-radius:45px; |
|||
overflow:hidden; |
|||
background-position:50%; |
|||
background-size:auto 90px; |
|||
box-shadow: 0 0 2px 2px rgba(208,208,208,128) inset; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo span { |
|||
display:inline-block; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo img { |
|||
height:90px; |
|||
position:relative; |
|||
left:-50%; |
|||
} |
|||
#wm-ipp #wm-capinfo .wm-title { |
|||
font-size:130%; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector { |
|||
display:inline-block; |
|||
color: #aaa; |
|||
text-decoration:none !important; |
|||
padding: 2px 8px; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector.selected { |
|||
background-color:#666; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector:hover { |
|||
color: #fff; |
|||
} |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-collected-by, |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-timestamps { |
|||
display: none; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content { |
|||
background-color:#ff0; |
|||
padding:5px; |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content * { |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-expand { |
|||
right: 1px; |
|||
bottom: -1px; |
|||
color: #ffffff; |
|||
background-color: #666 !important; |
|||
padding:0 5px 0 3px !important; |
|||
border-radius: 3px 3px 0 0 !important; |
|||
} |
|||
#wm-ipp #wm-expand span { |
|||
color: #ffffff; |
|||
} |
|||
#wm-ipp #wm-expand #wm-expand-icon { |
|||
display: inline-block; |
|||
transition: transform 0.5s; |
|||
transform-origin: 50% 45%; |
|||
} |
|||
#wm-ipp #wm-expand.wm-open #wm-expand-icon { |
|||
transform: rotate(180deg); |
|||
} |
|||
#wm-ipp #wmtb { |
|||
text-align:right; |
|||
} |
|||
#wm-ipp #wmtb #wmtbURL { |
|||
width: calc(100% - 45px); |
|||
} |
|||
#wm-ipp #wm-graph-anchor { |
|||
border-right:1px solid #ccc; |
|||
} |
|||
/* time coherence */ |
|||
html.wb-highlight { |
|||
box-shadow: inset 0 0 0 3px #a50e3a !important; |
|||
} |
|||
.wb-highlight { |
|||
outline: 3px solid #a50e3a !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:none !important; |
|||
} |
|||
@media print { |
|||
#wm-ipp-base { |
|||
display:none !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:block !important; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
} |
|||
@media (max-width:414px) { |
|||
#wm-ipp .xxs { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (min-width:1055px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:block !important; |
|||
} |
|||
} |
|||
@media (max-width:1054px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (max-width:1163px) { |
|||
#wm-logo { |
|||
display:none !important; |
|||
} |
|||
} |
|||
|
|||
#wm-btns { |
|||
white-space: nowrap; |
|||
margin-top: -2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-open { |
|||
margin-right: 7px; |
|||
top: -6px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in { |
|||
box-sizing: content-box; |
|||
display: none; |
|||
margin-right: 7px; |
|||
top: -8px; |
|||
|
|||
/* |
|||
round border around sign in button |
|||
*/ |
|||
border: 2px #000 solid; |
|||
border-radius: 14px; |
|||
padding-right: 2px; |
|||
padding-bottom: 2px; |
|||
width: 11px; |
|||
height: 11px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in>.iconochive-person { |
|||
font-size: 12.5px; |
|||
} |
|||
|
|||
#wm-save-snapshot-open > .iconochive-web { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-ipp #wm-share { |
|||
display: flex; |
|||
align-items: flex-end; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
#wm-share > #wm-screenshot { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-screenshot > .iconochive-image { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-share > #wm-video { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-video > .iconochive-movies { |
|||
color: #000; |
|||
display: inline-block; |
|||
font-size: 150%; |
|||
margin-bottom: 2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-in-progress { |
|||
display: none; |
|||
font-size:160%; |
|||
opacity: 0.5; |
|||
position: relative; |
|||
margin-right: 7px; |
|||
top: -5px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-success { |
|||
display: none; |
|||
color: green; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-fail { |
|||
display: none; |
|||
color: red; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
.wm-icon-screen-shot { |
|||
background: url("../images/web-screenshot.svg") no-repeat !important; |
|||
background-size: contain !important; |
|||
width: 22px !important; |
|||
height: 19px !important; |
|||
|
|||
display: inline-block; |
|||
} |
|||
#donato { |
|||
/* transition effect is disable so as to simplify height adjustment */ |
|||
/*transition: height 0.5s;*/ |
|||
height: 0; |
|||
margin: 0; |
|||
padding: 0; |
|||
border-bottom: 1px solid #999 !important; |
|||
} |
|||
body.wm-modal { |
|||
height: auto !important; |
|||
overflow: hidden !important; |
|||
} |
|||
#donato #donato-base { |
|||
width: 100%; |
|||
height: 100%; |
|||
/*bottom: 0;*/ |
|||
margin: 0; |
|||
padding: 0; |
|||
position: absolute; |
|||
z-index: 2147483639; |
|||
} |
|||
body.wm-modal #donato #donato-base { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 2147483640; |
|||
} |
|||
|
|||
.wb-autocomplete-suggestions { |
|||
font-family: Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size: 12px; |
|||
text-align: left; |
|||
cursor: default; |
|||
border: 1px solid #ccc; |
|||
border-top: 0; |
|||
background: #fff; |
|||
box-shadow: -1px 1px 3px rgba(0,0,0,.1); |
|||
position: absolute; |
|||
display: none; |
|||
z-index: 2147483647; |
|||
max-height: 254px; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
box-sizing: border-box; |
|||
} |
|||
.wb-autocomplete-suggestion { |
|||
position: relative; |
|||
padding: 0 .6em; |
|||
line-height: 23px; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
font-size: 1.02em; |
|||
color: #333; |
|||
} |
|||
.wb-autocomplete-suggestion b { |
|||
font-weight: bold; |
|||
} |
|||
.wb-autocomplete-suggestion.selected { |
|||
background: #f0f0f0; |
|||
} |
|||
3
Docs/Chapter 1.2 Drawing Graphics_files/bundle-playback.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,116 @@ |
|||
@font-face{font-family:'Iconochive-Regular';src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?-ccsheb');src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?#iefix-ccsheb') format('embedded-opentype'),url('https://archive.org/includes/fonts/Iconochive-Regular.woff?-ccsheb') format('woff'),url('https://archive.org/includes/fonts/Iconochive-Regular.ttf?-ccsheb') format('truetype'),url('https://archive.org/includes/fonts/Iconochive-Regular.svg?-ccsheb#Iconochive-Regular') format('svg');font-weight:normal;font-style:normal} |
|||
[class^="iconochive-"],[class*=" iconochive-"]{font-family:'Iconochive-Regular'!important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} |
|||
.iconochive-Uplevel:before{content:"\21b5"} |
|||
.iconochive-exit:before{content:"\1f6a3"} |
|||
.iconochive-beta:before{content:"\3b2"} |
|||
.iconochive-logo:before{content:"\1f3db"} |
|||
.iconochive-audio:before{content:"\1f568"} |
|||
.iconochive-movies:before{content:"\1f39e"} |
|||
.iconochive-software:before{content:"\1f4be"} |
|||
.iconochive-texts:before{content:"\1f56e"} |
|||
.iconochive-etree:before{content:"\1f3a4"} |
|||
.iconochive-image:before{content:"\1f5bc"} |
|||
.iconochive-web:before{content:"\1f5d4"} |
|||
.iconochive-collection:before{content:"\2211"} |
|||
.iconochive-folder:before{content:"\1f4c2"} |
|||
.iconochive-data:before{content:"\1f5c3"} |
|||
.iconochive-tv:before{content:"\1f4fa"} |
|||
.iconochive-article:before{content:"\1f5cf"} |
|||
.iconochive-question:before{content:"\2370"} |
|||
.iconochive-question-dark:before{content:"\3f"} |
|||
.iconochive-info:before{content:"\69"} |
|||
.iconochive-info-small:before{content:"\24d8"} |
|||
.iconochive-comment:before{content:"\1f5e9"} |
|||
.iconochive-comments:before{content:"\1f5ea"} |
|||
.iconochive-person:before{content:"\1f464"} |
|||
.iconochive-people:before{content:"\1f465"} |
|||
.iconochive-eye:before{content:"\1f441"} |
|||
.iconochive-rss:before{content:"\221e"} |
|||
.iconochive-time:before{content:"\1f551"} |
|||
.iconochive-quote:before{content:"\275d"} |
|||
.iconochive-disc:before{content:"\1f4bf"} |
|||
.iconochive-tv-commercial:before{content:"\1f4b0"} |
|||
.iconochive-search:before{content:"\1f50d"} |
|||
.iconochive-search-star:before{content:"\273d"} |
|||
.iconochive-tiles:before{content:"\229e"} |
|||
.iconochive-list:before{content:"\21f6"} |
|||
.iconochive-list-bulleted:before{content:"\2317"} |
|||
.iconochive-latest:before{content:"\2208"} |
|||
.iconochive-left:before{content:"\2c2"} |
|||
.iconochive-right:before{content:"\2c3"} |
|||
.iconochive-left-solid:before{content:"\25c2"} |
|||
.iconochive-right-solid:before{content:"\25b8"} |
|||
.iconochive-up-solid:before{content:"\25b4"} |
|||
.iconochive-down-solid:before{content:"\25be"} |
|||
.iconochive-dot:before{content:"\23e4"} |
|||
.iconochive-dots:before{content:"\25a6"} |
|||
.iconochive-columns:before{content:"\25af"} |
|||
.iconochive-sort:before{content:"\21d5"} |
|||
.iconochive-atoz:before{content:"\1f524"} |
|||
.iconochive-ztoa:before{content:"\1f525"} |
|||
.iconochive-upload:before{content:"\1f4e4"} |
|||
.iconochive-download:before{content:"\1f4e5"} |
|||
.iconochive-favorite:before{content:"\2605"} |
|||
.iconochive-heart:before{content:"\2665"} |
|||
.iconochive-play:before{content:"\25b6"} |
|||
.iconochive-play-framed:before{content:"\1f3ac"} |
|||
.iconochive-fullscreen:before{content:"\26f6"} |
|||
.iconochive-mute:before{content:"\1f507"} |
|||
.iconochive-unmute:before{content:"\1f50a"} |
|||
.iconochive-share:before{content:"\1f381"} |
|||
.iconochive-edit:before{content:"\270e"} |
|||
.iconochive-reedit:before{content:"\2710"} |
|||
.iconochive-gear:before{content:"\2699"} |
|||
.iconochive-remove-circle:before{content:"\274e"} |
|||
.iconochive-plus-circle:before{content:"\1f5d6"} |
|||
.iconochive-minus-circle:before{content:"\1f5d5"} |
|||
.iconochive-x:before{content:"\1f5d9"} |
|||
.iconochive-fork:before{content:"\22d4"} |
|||
.iconochive-trash:before{content:"\1f5d1"} |
|||
.iconochive-warning:before{content:"\26a0"} |
|||
.iconochive-flash:before{content:"\1f5f2"} |
|||
.iconochive-world:before{content:"\1f5fa"} |
|||
.iconochive-lock:before{content:"\1f512"} |
|||
.iconochive-unlock:before{content:"\1f513"} |
|||
.iconochive-twitter:before{content:"\1f426"} |
|||
.iconochive-facebook:before{content:"\66"} |
|||
.iconochive-googleplus:before{content:"\67"} |
|||
.iconochive-reddit:before{content:"\1f47d"} |
|||
.iconochive-tumblr:before{content:"\54"} |
|||
.iconochive-pinterest:before{content:"\1d4df"} |
|||
.iconochive-popcorn:before{content:"\1f4a5"} |
|||
.iconochive-email:before{content:"\1f4e7"} |
|||
.iconochive-embed:before{content:"\1f517"} |
|||
.iconochive-gamepad:before{content:"\1f579"} |
|||
.iconochive-Zoom_In:before{content:"\2b"} |
|||
.iconochive-Zoom_Out:before{content:"\2d"} |
|||
.iconochive-RSS:before{content:"\1f4e8"} |
|||
.iconochive-Light_Bulb:before{content:"\1f4a1"} |
|||
.iconochive-Add:before{content:"\2295"} |
|||
.iconochive-Tab_Activity:before{content:"\2318"} |
|||
.iconochive-Forward:before{content:"\23e9"} |
|||
.iconochive-Backward:before{content:"\23ea"} |
|||
.iconochive-No_Audio:before{content:"\1f508"} |
|||
.iconochive-Pause:before{content:"\23f8"} |
|||
.iconochive-No_Favorite:before{content:"\2606"} |
|||
.iconochive-Unike:before{content:"\2661"} |
|||
.iconochive-Song:before{content:"\266b"} |
|||
.iconochive-No_Flag:before{content:"\2690"} |
|||
.iconochive-Flag:before{content:"\2691"} |
|||
.iconochive-Done:before{content:"\2713"} |
|||
.iconochive-Check:before{content:"\2714"} |
|||
.iconochive-Refresh:before{content:"\27f3"} |
|||
.iconochive-Headphones:before{content:"\1f3a7"} |
|||
.iconochive-Chart:before{content:"\1f4c8"} |
|||
.iconochive-Bookmark:before{content:"\1f4d1"} |
|||
.iconochive-Documents:before{content:"\1f4da"} |
|||
.iconochive-Newspaper:before{content:"\1f4f0"} |
|||
.iconochive-Podcast:before{content:"\1f4f6"} |
|||
.iconochive-Radio:before{content:"\1f4fb"} |
|||
.iconochive-Cassette:before{content:"\1f4fc"} |
|||
.iconochive-Shuffle:before{content:"\1f500"} |
|||
.iconochive-Loop:before{content:"\1f501"} |
|||
.iconochive-Low_Audio:before{content:"\1f509"} |
|||
.iconochive-First:before{content:"\1f396"} |
|||
.iconochive-Invisible:before{content:"\1f576"} |
|||
.iconochive-Computer:before{content:"\1f5b3"} |
|||
@ -0,0 +1,876 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="430" |
|||
height="260" |
|||
viewBox="0 0 113.77083 68.79167" |
|||
version="1.1" |
|||
id="svg8" |
|||
sodipodi:docname="ordertable-buffercompare.svg" |
|||
inkscape:version="0.92.1 r15371"> |
|||
<defs |
|||
id="defs2"> |
|||
<marker |
|||
inkscape:stockid="TriangleOutM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker8518" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path8516" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleOutM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker8376" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path8374" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker8306" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleOutM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path8304" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker8296" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleOutM"> |
|||
<path |
|||
transform="scale(0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path8294" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker8220" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleOutM"> |
|||
<path |
|||
transform="scale(0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path8218" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleOutM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="TriangleOutM" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path7287" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Send" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker8024" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path8022" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="matrix(-0.3,0,0,-0.3,0.69,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker7876" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleOutS"> |
|||
<path |
|||
transform="scale(0.2)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path7874" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker7696" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path7694" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker7578" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path7576" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker7096" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mend"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path7094" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6521" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mend"> |
|||
<path |
|||
transform="scale(-0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path6519" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6517" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mend"> |
|||
<path |
|||
transform="scale(-0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path6515" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6513" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mend"> |
|||
<path |
|||
transform="scale(-0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path6511" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9871" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.4,0,0,-0.4,-4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker9806" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9804" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker6984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path6982" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5944" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5942" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5328" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5326" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5883" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5881" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5705" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5703" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4561" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(0.4,0,0,0.4,4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Send" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Send" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4570" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
</defs> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1.4142136" |
|||
inkscape:cx="79.63324" |
|||
inkscape:cy="106.88666" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="true" |
|||
units="px" |
|||
inkscape:snap-bbox="false" |
|||
inkscape:snap-bbox-edge-midpoints="true" |
|||
inkscape:snap-nodes="true" |
|||
inkscape:snap-others="true" |
|||
inkscape:object-nodes="true" |
|||
inkscape:snap-midpoints="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:bbox-nodes="false" |
|||
inkscape:object-paths="true" |
|||
inkscape:snap-global="true" |
|||
inkscape:snap-text-baseline="true" |
|||
showguides="true" |
|||
inkscape:guide-bbox="true"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-512,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,135.46666" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,135.46666" |
|||
orientation="512,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid5858" /> |
|||
<sodipodi:guide |
|||
position="88.635414,66.145836" |
|||
orientation="1,0" |
|||
id="guide6770" |
|||
inkscape:locked="false" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title></dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-228.20831)"> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="5.2916665" |
|||
y="234.82289" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="29.104166" |
|||
y="237.46872" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="29.104166" |
|||
y="237.46872" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Process graphics to OT</tspan></text> |
|||
<text |
|||
id="text5550" |
|||
y="242.76039" |
|||
x="29.104168" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="242.76039" |
|||
x="29.104168" |
|||
id="tspan5548" |
|||
sodipodi:role="line">OT sent to GPU</tspan></text> |
|||
<text |
|||
id="text4576" |
|||
y="237.46872" |
|||
x="88.635414" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="237.46872" |
|||
x="88.635414" |
|||
id="tspan4574" |
|||
sodipodi:role="line">GPU idle</tspan></text> |
|||
<flowRoot |
|||
xml:space="preserve" |
|||
id="flowRoot4578" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
transform="matrix(0.26458333,0,0,0.26458333,1.5894572e-7,246.72913)"><flowRegion |
|||
id="flowRegion4580"><rect |
|||
id="rect4582" |
|||
width="209.5" |
|||
height="83.5" |
|||
x="234.5" |
|||
y="-44" /></flowRegion><flowPara |
|||
id="flowPara4584" /></flowRoot> <text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="88.635414" |
|||
y="242.76039" |
|||
id="text4590"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4588" |
|||
x="88.635414" |
|||
y="242.76039" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">GPU busy</tspan></text> |
|||
<text |
|||
id="text4596" |
|||
y="248.05206" |
|||
x="29.104166" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="248.05206" |
|||
x="29.104166" |
|||
id="tspan4594" |
|||
sodipodi:role="line">Process graphics to OT</tspan></text> |
|||
<text |
|||
id="text4602" |
|||
y="248.05206" |
|||
x="88.635414" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="248.05206" |
|||
x="88.635414" |
|||
id="tspan4600" |
|||
sodipodi:role="line">GPU busy</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="29.104168" |
|||
y="258.63541" |
|||
id="text4608"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4606" |
|||
x="29.104168" |
|||
y="258.63541" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT sent to GPU</tspan></text> |
|||
<text |
|||
id="text4614" |
|||
y="258.63541" |
|||
x="88.635414" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="258.63541" |
|||
x="88.635414" |
|||
id="tspan4612" |
|||
sodipodi:role="line">GPU busy</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker8376);paint-order:normal" |
|||
d="m 54.239583,241.96664 h 7.9375" |
|||
id="path4640" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker8518);paint-order:normal" |
|||
d="m 54.239583,257.84164 h 7.9375" |
|||
id="path4642" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cc" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="29.104168" |
|||
y="253.34372" |
|||
id="text4650"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4648" |
|||
x="29.104168" |
|||
y="253.34372" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Wait for GPU (DrawSync())</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="88.635414" |
|||
y="253.34372" |
|||
id="text4656"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4654" |
|||
x="88.635414" |
|||
y="253.34372" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">GPU finished</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker8306);paint-order:normal" |
|||
d="M 5.2916669,257.84164 H 1.5875 L 1.3229167,257.57706 V 247.52289 L 1.5875,247.25831 h 2.3812502" |
|||
id="path4658" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<text |
|||
id="text5925" |
|||
y="271.86456" |
|||
x="29.104166" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="271.86456" |
|||
x="29.104166" |
|||
id="tspan5923" |
|||
sodipodi:role="line">Process graphics to OT</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="88.635414" |
|||
y="271.86456" |
|||
id="text5931"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5929" |
|||
x="88.635414" |
|||
y="271.86456" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">GPU idle</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="29.104168" |
|||
y="277.15625" |
|||
id="text5937"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5935" |
|||
x="29.104168" |
|||
y="277.15625" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT sent to GPU</tspan></text> |
|||
<text |
|||
id="text5943" |
|||
y="277.15625" |
|||
x="88.635414" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="277.15625" |
|||
x="88.635414" |
|||
id="tspan5941" |
|||
sodipodi:role="line">GPU busy</tspan></text> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5945" |
|||
d="m 54.239583,276.36248 h 7.927435" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#TriangleOutM);paint-order:normal" |
|||
sodipodi:nodetypes="cc" /> |
|||
<text |
|||
id="text5951" |
|||
y="282.44791" |
|||
x="29.104168" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="282.44791" |
|||
x="29.104168" |
|||
id="tspan5949" |
|||
sodipodi:role="line">Wait for GPU (DrawSync())</tspan></text> |
|||
<text |
|||
id="text5957" |
|||
y="282.44791" |
|||
x="88.635414" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="282.44791" |
|||
x="88.635414" |
|||
id="tspan5955" |
|||
sodipodi:role="line">GPU finished</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="88.635414" |
|||
y="287.73956" |
|||
id="text5963"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5961" |
|||
x="88.635414" |
|||
y="287.73956" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">GPU idle</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="29.104166" |
|||
y="287.73956" |
|||
id="text5969"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5967" |
|||
x="29.104166" |
|||
y="287.73956" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Process graphics to OT</tspan></text> |
|||
<text |
|||
id="text5975" |
|||
y="293.03125" |
|||
x="29.104168" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="293.03125" |
|||
x="29.104168" |
|||
id="tspan5973" |
|||
sodipodi:role="line">OT sent to GPU</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="88.635414" |
|||
y="293.03125" |
|||
id="text5981"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5979" |
|||
x="88.635414" |
|||
y="293.03125" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">GPU busy</tspan></text> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5983" |
|||
d="m 54.239583,292.23748 h 7.927435" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker8220);paint-order:normal" |
|||
sodipodi:nodetypes="cc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path6151" |
|||
d="M 5.2916669,292.23748 H 1.8520834 l -0.5291667,-0.52917 v -9.525 l 0.5291667,-0.52917 h 2.1166668" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker8296);paint-order:normal" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="1.3229167" |
|||
y="266.57291" |
|||
id="text9977"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan9975" |
|||
x="1.3229167" |
|||
y="266.57291" |
|||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26499999">Single OT+Prim. Buffer</tspan></text> |
|||
<text |
|||
id="text9981" |
|||
y="232.17706" |
|||
x="1.3229167" |
|||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26499999" |
|||
y="232.17706" |
|||
x="1.3229167" |
|||
id="tspan9979" |
|||
sodipodi:role="line">Double OT+Prim. Buffer</tspan></text> |
|||
<rect |
|||
y="240.11456" |
|||
x="5.2916665" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect5860" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5862" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="5.2916665" |
|||
y="245.40622" /> |
|||
<rect |
|||
y="250.69789" |
|||
x="5.2916665" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect5864" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5866" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="5.2916665" |
|||
y="255.98956" /> |
|||
<rect |
|||
y="234.82289" |
|||
x="63.5" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect5868" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5870" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="63.5" |
|||
y="240.11456" /> |
|||
<rect |
|||
y="245.40622" |
|||
x="63.5" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect5872" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5874" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="63.5" |
|||
y="250.69789" /> |
|||
<rect |
|||
y="255.98956" |
|||
x="63.5" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect5876" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
y="269.21875" |
|||
x="5.2916665" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect6520" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect6522" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="5.2916656" |
|||
y="274.51041" /> |
|||
<rect |
|||
y="279.80206" |
|||
x="5.2916665" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect6524" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect6526" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="5.2916665" |
|||
y="285.09375" /> |
|||
<rect |
|||
y="290.38541" |
|||
x="5.2916665" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect6528" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect6772" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="63.5" |
|||
y="269.21875" /> |
|||
<rect |
|||
y="274.51041" |
|||
x="63.499996" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect6774" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect6776" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="63.5" |
|||
y="279.80206" /> |
|||
<rect |
|||
y="285.09375" |
|||
x="63.5" |
|||
height="3.9687502" |
|||
width="48.947918" |
|||
id="rect6778" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect6780" |
|||
width="48.947918" |
|||
height="3.9687502" |
|||
x="63.5" |
|||
y="290.38541" /> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,705 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="420" |
|||
height="220" |
|||
viewBox="0 0 111.125 58.208337" |
|||
version="1.1" |
|||
id="svg8" |
|||
sodipodi:docname="ordertable-multiprims.svg" |
|||
inkscape:version="0.92.1 r15371"> |
|||
<defs |
|||
id="defs2"> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker7807" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path7805" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker7561" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path7559" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6581" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path6579" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6049" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path6047" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5905" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path5903" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9889" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9871" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.4,0,0,-0.4,-4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker9806" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9804" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker6984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path6982" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5944" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5942" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5328" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5326" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5883" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5881" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5705" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5703" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4561" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(0.4,0,0,0.4,4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Send" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Send" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4570" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4982" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker13622" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path13620" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4575" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4573" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4587" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4585" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4593" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4591" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4599" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4597" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4605" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4603" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
</defs> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1" |
|||
inkscape:cx="298.22087" |
|||
inkscape:cy="212.17404" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="false" |
|||
units="px" |
|||
inkscape:snap-bbox="false" |
|||
inkscape:snap-bbox-edge-midpoints="true" |
|||
inkscape:snap-nodes="true" |
|||
inkscape:snap-others="true" |
|||
inkscape:object-nodes="true" |
|||
inkscape:snap-midpoints="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:bbox-nodes="false" |
|||
inkscape:object-paths="true" |
|||
inkscape:snap-global="true" |
|||
inkscape:snap-text-baseline="true"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-512,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,135.46666" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,135.46666" |
|||
orientation="512,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid5333" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title></dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-238.79163)"> |
|||
<text |
|||
id="text7984" |
|||
y="267.10205" |
|||
x="85.989586" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="267.10205" |
|||
x="85.989586" |
|||
id="tspan7982" |
|||
sodipodi:role="line">Primitive 2</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="240.1145" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="244.08325" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="31.750002" |
|||
y="244.08325" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[0]=0xffffffff (end)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
id="text4545"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4543" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Start of table</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4984);paint-order:normal" |
|||
d="m 5.5562491,242.76034 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
id="path4553" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="246.72908" |
|||
x="6.6145835" |
|||
height="5.2916694" |
|||
width="48.947918" |
|||
id="rect5546" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5550" |
|||
y="250.69783" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="250.69783" |
|||
x="31.750002" |
|||
id="tspan5548" |
|||
sodipodi:role="line">OT[1]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5576" |
|||
width="48.947918" |
|||
height="5.2916741" |
|||
x="6.6145835" |
|||
y="253.34367" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
id="text5580"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5578" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[2]</tspan></text> |
|||
<rect |
|||
y="259.95831" |
|||
x="6.6145835" |
|||
height="5.2916636" |
|||
width="48.947918" |
|||
id="rect5582" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5586" |
|||
y="263.92706" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="263.92706" |
|||
x="31.750002" |
|||
id="tspan5584" |
|||
sodipodi:role="line">OT[3]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5588" |
|||
width="48.947918" |
|||
height="5.2916536" |
|||
x="6.6145835" |
|||
y="266.57288" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
id="text5592"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5590" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[4]</tspan></text> |
|||
<rect |
|||
y="273.18747" |
|||
x="6.6145835" |
|||
height="5.2916741" |
|||
width="48.947918" |
|||
id="rect5594" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5598" |
|||
y="277.15622" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="277.15622" |
|||
x="31.750002" |
|||
id="tspan5596" |
|||
sodipodi:role="line">OT[5]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5600" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="279.80203" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
id="text5604"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5602" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[6]</tspan></text> |
|||
<rect |
|||
y="286.41666" |
|||
x="6.6145835" |
|||
height="5.2916536" |
|||
width="48.947918" |
|||
id="rect5606" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5610" |
|||
y="290.38541" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="290.38541" |
|||
x="31.750002" |
|||
id="tspan5608" |
|||
sodipodi:role="line">OT[7]</tspan></text> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path13452" |
|||
d="m 56.620832,249.37492 2.381253,1e-5 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 h -3.439586" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker13622);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4571" |
|||
d="m 5.5562491,255.98951 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4575);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4587);paint-order:normal" |
|||
d="m 5.5562491,269.21868 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
id="path4583" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4589" |
|||
d="m 56.620832,275.83325 2.381253,10e-6 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 h -3.439586" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4593);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4595" |
|||
d="m 5.5562491,282.44784 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4599);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4605);paint-order:normal" |
|||
d="m 56.620832,289.06242 2.381253,1e-5 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 4.23333 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 H 42.333332" |
|||
id="path4601" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="263.39789" |
|||
x="68.791664" |
|||
height="5.2916584" |
|||
width="35.718754" |
|||
id="rect5707" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6049);paint-order:normal" |
|||
d="m 67.733333,272.39371 h -5.55625 c -1.852082,0 -0.529166,-3.17499 -2.645833,-3.17499 h -3.968751" |
|||
id="path6033" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6581);paint-order:normal" |
|||
d="m 56.620833,262.60413 h 2.910416 c 2.116668,0 0.529165,-7.9375 2.645831,-7.9375 h 44.97917 c 0.79375,0 1.32292,0.52917 1.32292,1.32292 l 0,2.11666 c 0,0.79375 -0.52917,1.32292 -1.30202,1.32292 h -2.66673" |
|||
id="path6571" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccccc" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect7433" |
|||
width="35.718754" |
|||
height="5.2916689" |
|||
x="68.791664" |
|||
y="256.78329" /> |
|||
<rect |
|||
y="270.01245" |
|||
x="68.791664" |
|||
height="5.2916789" |
|||
width="35.718754" |
|||
id="rect7435" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker7561);paint-order:normal" |
|||
d="m 105.56875,266.04371 2.38126,1e-5 c 0.26458,0 0.52916,0.26458 0.52916,0.52917 v 5.55625 c 0,0.26458 -0.26458,0.52916 -0.52916,0.52916 h -3.43959" |
|||
id="path7557" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path7803" |
|||
d="m 67.733333,259.42913 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker7807);paint-order:normal" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="85.989586" |
|||
y="260.48746" |
|||
id="text8261"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan8259" |
|||
x="85.989586" |
|||
y="260.48746" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Primitive 1</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="85.989586" |
|||
y="273.71664" |
|||
id="text8265"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan8263" |
|||
x="85.989586" |
|||
y="273.71664" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Primitive 3</tspan></text> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,657 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="420" |
|||
height="220" |
|||
viewBox="0 0 111.125 58.208337" |
|||
version="1.1" |
|||
id="svg8" |
|||
sodipodi:docname="ordertable-primitive.svg" |
|||
inkscape:version="0.92.1 r15371"> |
|||
<defs |
|||
id="defs2"> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker7807" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path7805" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker7561" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path7559" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6581" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path6579" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6049" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path6047" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5905" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path5903" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9889" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9871" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.4,0,0,-0.4,-4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker9806" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9804" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker6984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path6982" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5944" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5942" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5328" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5326" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5883" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5881" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5705" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5703" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4561" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(0.4,0,0,0.4,4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Send" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Send" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4570" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4982" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker13622" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path13620" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4575" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4573" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4587" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4585" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4593" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4591" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4599" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4597" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4605" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4603" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
</defs> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="6.8701326" |
|||
inkscape:cx="331.92997" |
|||
inkscape:cy="122.79977" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="true" |
|||
units="px" |
|||
inkscape:snap-bbox="false" |
|||
inkscape:snap-bbox-edge-midpoints="true" |
|||
inkscape:snap-nodes="true" |
|||
inkscape:snap-others="true" |
|||
inkscape:object-nodes="true" |
|||
inkscape:snap-midpoints="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:bbox-nodes="false" |
|||
inkscape:object-paths="true" |
|||
inkscape:snap-global="true" |
|||
inkscape:snap-text-baseline="true"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-512,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,135.46666" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,135.46666" |
|||
orientation="512,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid5333" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title /> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-238.79163)"> |
|||
<text |
|||
id="text7984" |
|||
y="267.10205" |
|||
x="85.989586" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="267.10205" |
|||
x="85.989586" |
|||
id="tspan7982" |
|||
sodipodi:role="line">Primitive</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="240.1145" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="244.08325" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="31.750002" |
|||
y="244.08325" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[0]=0xffffffff (end)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
id="text4545"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4543" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Start of table</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4984);paint-order:normal" |
|||
d="m 5.5562491,242.76034 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
id="path4553" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="246.72908" |
|||
x="6.6145835" |
|||
height="5.2916694" |
|||
width="48.947918" |
|||
id="rect5546" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5550" |
|||
y="250.69783" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="250.69783" |
|||
x="31.750002" |
|||
id="tspan5548" |
|||
sodipodi:role="line">OT[1]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5576" |
|||
width="48.947918" |
|||
height="5.2916741" |
|||
x="6.6145835" |
|||
y="253.34367" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
id="text5580"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5578" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[2]</tspan></text> |
|||
<rect |
|||
y="259.95831" |
|||
x="6.6145835" |
|||
height="5.2916636" |
|||
width="48.947918" |
|||
id="rect5582" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5586" |
|||
y="263.92706" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="263.92706" |
|||
x="31.750002" |
|||
id="tspan5584" |
|||
sodipodi:role="line">OT[3]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5588" |
|||
width="48.947918" |
|||
height="5.2916536" |
|||
x="6.6145835" |
|||
y="266.57288" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
id="text5592"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5590" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[4]</tspan></text> |
|||
<rect |
|||
y="273.18747" |
|||
x="6.6145835" |
|||
height="5.2916741" |
|||
width="48.947918" |
|||
id="rect5594" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5598" |
|||
y="277.15622" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="277.15622" |
|||
x="31.750002" |
|||
id="tspan5596" |
|||
sodipodi:role="line">OT[5]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5600" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="279.80203" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
id="text5604"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5602" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[6]</tspan></text> |
|||
<rect |
|||
y="286.41666" |
|||
x="6.6145835" |
|||
height="5.2916536" |
|||
width="48.947918" |
|||
id="rect5606" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5610" |
|||
y="290.38541" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="290.38541" |
|||
x="31.750002" |
|||
id="tspan5608" |
|||
sodipodi:role="line">OT[7]</tspan></text> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path13452" |
|||
d="m 56.620832,249.37492 2.381253,1e-5 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 h -3.439586" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker13622);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4571" |
|||
d="m 5.5562491,255.98951 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4575);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4587);paint-order:normal" |
|||
d="m 5.5562491,269.21868 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
id="path4583" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4589" |
|||
d="m 56.620832,275.83325 2.381253,10e-6 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 h -3.439586" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4593);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4595" |
|||
d="m 5.5562491,282.44784 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4599);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4605);paint-order:normal" |
|||
d="m 56.620832,289.06242 2.381253,1e-5 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 4.23333 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 H 42.333332" |
|||
id="path4601" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="263.39789" |
|||
x="68.791664" |
|||
height="5.2916584" |
|||
width="35.718754" |
|||
id="rect5707" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6049);paint-order:normal" |
|||
d="m 67.733334,266.04372 h -5.55625 c -1.852082,0 -0.529166,3.17499 -2.645833,3.17499 H 55.5625" |
|||
id="path6033" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6581);paint-order:normal" |
|||
d="m 56.620833,262.60413 h 2.910416 c 2.116668,0 0.529162,-2.64584 2.645828,-2.64584 h 44.979173 c 0.79375,0 1.32292,0.52917 1.32292,1.32292 v 3.43958 c 0,0.79375 -0.52917,1.32292 -1.30202,1.32292 h -2.66673" |
|||
id="path6571" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccccc" /> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,633 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="235" |
|||
height="220" |
|||
viewBox="0 0 62.177082 58.208337" |
|||
version="1.1" |
|||
id="svg8" |
|||
sodipodi:docname="ordertable.svg" |
|||
inkscape:version="0.92.1 r15371"> |
|||
<defs |
|||
id="defs2"> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4605" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4603" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4599" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4597" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4593" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4591" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4587" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4585" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4581" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4579" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4575" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4573" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker13622" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path13620" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4982" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInL" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="TriangleInL" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4691" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.8)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="TriangleInM" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4694" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Lstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Lstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4576" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="matrix(1.1,0,0,1.1,1.1,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Lstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Lstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4558" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(0.8,0,0,0.8,10,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Mstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4582" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Sstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Sstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4588" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="matrix(0.3,0,0,0.3,-0.69,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker7236" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path7234" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker6984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path6982" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5944" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5942" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5328" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5326" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5883" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5881" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5705" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5703" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4561" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(0.4,0,0,0.4,4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Send" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Send" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4570" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
</defs> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="2.8284271" |
|||
inkscape:cx="72.018278" |
|||
inkscape:cy="110.6517" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="true" |
|||
units="px" |
|||
inkscape:snap-bbox="false" |
|||
inkscape:snap-bbox-edge-midpoints="true" |
|||
inkscape:snap-nodes="true" |
|||
inkscape:snap-others="true" |
|||
inkscape:object-nodes="true" |
|||
inkscape:snap-midpoints="false" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:bbox-nodes="false" |
|||
inkscape:object-paths="false" |
|||
inkscape:snap-global="true" |
|||
inkscape:snap-text-baseline="true" |
|||
inkscape:snap-smooth-nodes="false"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-512,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,135.46666" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,135.46666" |
|||
orientation="512,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid4556" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title></dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-238.79163)"> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="240.11455" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="244.0833" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="31.750002" |
|||
y="244.0833" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[0]=0xffffffff (end)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
id="text4545"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4543" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Start of table</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4984);paint-order:normal" |
|||
d="m 5.5562498,242.76037 h -2.38125 c -0.2645834,0 -0.5291667,0.26458 -0.5291667,0.52917 v 5.55625 c 0,0.26458 0.2645833,0.52916 0.5291667,0.52916 h 3.4395833" |
|||
id="path4553" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="246.72913" |
|||
x="6.6145835" |
|||
height="5.2916689" |
|||
width="48.947918" |
|||
id="rect5546" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5550" |
|||
y="250.69788" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="250.69788" |
|||
x="31.750002" |
|||
id="tspan5548" |
|||
sodipodi:role="line">OT[1]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5576" |
|||
width="48.947918" |
|||
height="5.2916741" |
|||
x="6.6145835" |
|||
y="253.3437" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
id="text5580"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5578" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[2]</tspan></text> |
|||
<rect |
|||
y="259.95828" |
|||
x="6.6145835" |
|||
height="5.2916636" |
|||
width="48.947918" |
|||
id="rect5582" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5586" |
|||
y="263.92703" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="263.92703" |
|||
x="31.750002" |
|||
id="tspan5584" |
|||
sodipodi:role="line">OT[3]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5588" |
|||
width="48.947918" |
|||
height="5.2916536" |
|||
x="6.6145835" |
|||
y="266.57288" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
id="text5592"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5590" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[4]</tspan></text> |
|||
<rect |
|||
y="273.18744" |
|||
x="6.6145835" |
|||
height="5.2916741" |
|||
width="48.947918" |
|||
id="rect5594" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5598" |
|||
y="277.15619" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="277.15619" |
|||
x="31.750002" |
|||
id="tspan5596" |
|||
sodipodi:role="line">OT[5]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5600" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="279.80203" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
id="text5604"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5602" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[6]</tspan></text> |
|||
<rect |
|||
y="286.41663" |
|||
x="6.6145835" |
|||
height="5.2916536" |
|||
width="48.947918" |
|||
id="rect5606" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5610" |
|||
y="290.38538" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="290.38538" |
|||
x="31.750002" |
|||
id="tspan5608" |
|||
sodipodi:role="line">OT[7]</tspan></text> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path13452" |
|||
d="m 56.620833,249.37495 2.381251,10e-6 c 0.264583,0 0.529166,0.26458 0.529166,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529166,0.52916 H 55.5625" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker13622);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4571" |
|||
d="m 5.5562498,255.98954 h -2.38125 c -0.2645834,0 -0.5291667,0.26458 -0.5291667,0.52917 v 5.55625 c 0,0.26458 0.2645833,0.52916 0.5291667,0.52916 h 3.4395833" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4575);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4581);paint-order:normal" |
|||
d="m 56.620833,262.60411 2.381251,1e-5 c 0.264583,0 0.529166,0.26458 0.529166,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529166,0.52916 H 55.5625" |
|||
id="path4577" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4587);paint-order:normal" |
|||
d="m 5.5562498,269.21871 h -2.38125 c -0.2645834,0 -0.5291667,0.26458 -0.5291667,0.52917 v 5.55625 c 0,0.26458 0.2645833,0.52916 0.5291667,0.52916 h 3.4395833" |
|||
id="path4583" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4589" |
|||
d="m 56.620833,275.83328 2.381251,10e-6 c 0.264583,0 0.529166,0.26458 0.529166,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529166,0.52916 H 55.5625" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4593);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4595" |
|||
d="m 5.5562498,282.44787 h -2.38125 c -0.2645834,0 -0.5291667,0.26458 -0.5291667,0.52917 v 5.55625 c 0,0.26458 0.2645833,0.52916 0.5291667,0.52916 h 3.4395833" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4599);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4605);paint-order:normal" |
|||
d="m 56.620833,289.06245 2.381251,10e-6 c 0.264583,0 0.529166,0.26458 0.529166,0.52917 v 4.23333 c 0,0.26458 -0.264583,0.52916 -0.529166,0.52916 H 42.333333" |
|||
id="path4601" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,350 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="210" |
|||
height="120" |
|||
viewBox="0 0 55.562499 31.750002" |
|||
version="1.1" |
|||
id="svg8" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="primstruct.svg"> |
|||
<defs |
|||
id="defs2" /> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="2.8284271" |
|||
inkscape:cx="86.433235" |
|||
inkscape:cy="88.08852" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="true" |
|||
units="px" |
|||
inkscape:snap-midpoints="true" |
|||
inkscape:object-paths="true" |
|||
inkscape:snap-text-baseline="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:snap-intersection-paths="true" |
|||
showborder="true"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,300" |
|||
id="guide4618" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="79.375,0" |
|||
orientation="-200,0" |
|||
id="guide4620" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="79.375,52.916667" |
|||
orientation="0,-300" |
|||
id="guide4622" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,52.916667" |
|||
orientation="200,0" |
|||
id="guide4624" |
|||
inkscape:locked="false" /> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid4537" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title /> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-265.24996)"> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="47.625" |
|||
y="267.89578" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="47.625" |
|||
y="267.89578" |
|||
style="text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">31</tspan></text> |
|||
<text |
|||
id="text4501" |
|||
y="267.89578" |
|||
x="2.6458333" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="267.89578" |
|||
x="2.6458333" |
|||
id="tspan4499" |
|||
sodipodi:role="line">0</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="19.84375" |
|||
y="273.18747" |
|||
id="text4534"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4532" |
|||
x="19.84375" |
|||
y="273.18747" |
|||
style="text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Next Pointer</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="44.979168" |
|||
y="273.18747" |
|||
id="text4538"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4536" |
|||
x="44.979168" |
|||
y="273.18747" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">Len</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="7.7092853" |
|||
y="278.45084" |
|||
id="text4542"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4540" |
|||
x="7.7092853" |
|||
y="278.45084" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">R</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="20.372917" |
|||
y="278.47913" |
|||
id="text4546"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4544" |
|||
x="20.372917" |
|||
y="278.47913" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">G</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="32.279167" |
|||
y="278.47913" |
|||
id="text4550"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4548" |
|||
x="32.279167" |
|||
y="278.47913" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">B</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="44.979168" |
|||
y="278.47913" |
|||
id="text4554"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4552" |
|||
x="44.979168" |
|||
y="278.47913" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">Code</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="14.552083" |
|||
y="283.77078" |
|||
id="text4558"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4556" |
|||
x="14.552083" |
|||
y="283.77078" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">X</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="39.6875" |
|||
y="283.77078" |
|||
id="text4562"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4560" |
|||
x="39.6875" |
|||
y="283.77078" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">Y</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="7.9375" |
|||
y="289.06247" |
|||
id="text4566"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4564" |
|||
x="7.9375" |
|||
y="289.06247" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">U</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="21.166666" |
|||
y="289.06247" |
|||
id="text4570"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4568" |
|||
x="21.166666" |
|||
y="289.06247" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">V</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="39.6875" |
|||
y="289.06247" |
|||
id="text4574"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4572" |
|||
x="39.6875" |
|||
y="289.06247" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">CLUT</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="14.552083" |
|||
y="294.35413" |
|||
id="text4582"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4580" |
|||
x="14.552083" |
|||
y="294.35413" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">Width</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:start;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="39.6875" |
|||
y="294.35413" |
|||
id="text4586"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4584" |
|||
x="39.6875" |
|||
y="294.35413" |
|||
style="text-align:center;text-anchor:middle;stroke-width:0.26458332">Height</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4590" |
|||
width="25.135416" |
|||
height="5.2916675" |
|||
x="1.3229166" |
|||
y="290.38538" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4592" |
|||
width="25.135416" |
|||
height="5.2916675" |
|||
x="26.458334" |
|||
y="290.38538" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4594" |
|||
width="13.229167" |
|||
height="5.2524114" |
|||
x="1.3229166" |
|||
y="285.13297" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4598" |
|||
width="25.135416" |
|||
height="5.291657" |
|||
x="26.458334" |
|||
y="285.09372" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4600" |
|||
width="25.135416" |
|||
height="5.2916775" |
|||
x="26.458334" |
|||
y="279.80203" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4602" |
|||
width="25.135416" |
|||
height="5.2916775" |
|||
x="1.3229166" |
|||
y="279.80203" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4604" |
|||
width="13.229167" |
|||
height="5.2916675" |
|||
x="1.3229166" |
|||
y="274.51038" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4606" |
|||
width="11.90625" |
|||
height="5.2916675" |
|||
x="14.552083" |
|||
y="274.51038" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4608" |
|||
width="11.906249" |
|||
height="5.2916675" |
|||
x="26.458334" |
|||
y="274.51038" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4610" |
|||
width="13.229168" |
|||
height="5.2916675" |
|||
x="38.364582" |
|||
y="274.51038" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4612" |
|||
width="13.229168" |
|||
height="5.291657" |
|||
x="38.364582" |
|||
y="269.21872" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4614" |
|||
width="37.041668" |
|||
height="5.291657" |
|||
x="1.3229166" |
|||
y="269.21872" /> |
|||
<rect |
|||
y="285.09372" |
|||
x="14.552083" |
|||
height="5.291657" |
|||
width="11.90625" |
|||
id="rect4616" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
y="274.51038" |
|||
x="26.458334" |
|||
height="5.2916675" |
|||
width="11.906249" |
|||
id="rect4539" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,70 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
/* |
|||
FILE ARCHIVED ON 03:35:25 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:39:09 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
*/ |
|||
/* |
|||
playback timings (ms): |
|||
captures_list: 107.165 |
|||
exclusion.robots: 0.073 |
|||
exclusion.robots.policy: 0.067 |
|||
cdx.remote: 0.064 |
|||
esindex: 0.009 |
|||
LoadShardBlock: 52.713 (3) |
|||
PetaboxLoader3.datanode: 140.466 (4) |
|||
CDXLines.iter: 14.771 (3) |
|||
load_resource: 139.896 |
|||
PetaboxLoader3.resolve: 47.824 |
|||
*/ |
|||
21
Docs/Chapter 1.2 Drawing Graphics_files/wombat.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,919 @@ |
|||
<html><head> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/style.css"> |
|||
<title>Chapter 1.3: Textures, TPages and CLUTs</title> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
|||
</head> |
|||
<body> |
|||
|
|||
<header> |
|||
<h1>Chapter 1.3: Textures, TPages and CLUTs</h1> |
|||
</header> |
|||
<p> |
|||
This tutorial will teach you how to draw graphics with textures, from |
|||
converting texture data to loading it onto VRAM, and finally drawing said |
|||
texture. This is yet another essential part in PS1 graphics programming, |
|||
as not having any textures would not always make for a pretty looking game. |
|||
</p> |
|||
<p> |
|||
This chapter will also cover some development tools to be used for |
|||
preparing texture data, such as <b>timtool</b> and <b>img2tim</b>. |
|||
</p> |
|||
<p> |
|||
<b>Compatible with PSn00bSDK:</b> Yes |
|||
</p> |
|||
|
|||
<h2>Tutorial Index</h2> |
|||
<ul> |
|||
<li><a href="#textures">Textures</a></li> |
|||
<li><a href="#cluts">Color Look-up Tables (CLUT)</a></li> |
|||
<li><a href="#texaddr">Texture Addressing on the PS1</a></li> |
|||
<li><a href="#seltexpage">Defining and Selecting a Texture Page</a></li> |
|||
<li><a href="#maketexture">Creating a TIM Texture Image</a></li> |
|||
<li><a href="#inctexture">Including TIM Image Data</a></li> |
|||
<li><a href="#tipsandtricks">Tips, Tricks and Improvements</a></li> |
|||
<li><a href="#conclusion">Conclusion</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="textures">Textures</h2> |
|||
<p> |
|||
A texture in the context of graphics programming, is basically a bitmap |
|||
of pixels that can either be drawn to the screen as a 2D image or |
|||
mapped onto polygons to add textures on 3D models. |
|||
</p> |
|||
<p> |
|||
On the PS1 hardware, textures are naturally stored in VRAM alongside the |
|||
display and drawing buffers described in previous tutorials. Textures are |
|||
generally positioned outside of said visual areas so to not get overwritten |
|||
by graphics frames drawn by the GPU. Once texture images have been loaded, |
|||
it can then be drawn by textured sprite and/or polygon primitives. |
|||
</p> |
|||
<p> |
|||
The PS1 supports texture color depths of 4, 8 and 16 bits per pixel. 4-bit |
|||
and 8-bit textures are usually accompanied with CLUT or Color Lookup Table. |
|||
A CLUT is essentially the color palette of its associated texture image. |
|||
</p> |
|||
<p> |
|||
Because the VRAM addresses pixels in 16-bit words, 4-bit and 8-bit textures |
|||
are stored at quarter and half of the actual width of the texture respectively |
|||
as shown in the image below. |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/vram-texture-widths.png"> |
|||
<i>4-bit, 8-bit and 16-bit texture images as they appear logically in VRAM</i> |
|||
</center> |
|||
<p> |
|||
This also means that 8-bit textures must have a width that is of a multiple |
|||
of 2 whilst 4-bit textures must be of a multiple of 4 to ensure that the pixel |
|||
data is word-aligned in VRAM. Failing to do so will often yield artifacts, or |
|||
corrupted texture images when trying to upload odd-width images into VRAM. |
|||
</p> |
|||
<p> |
|||
Texture images are usually handled on the PS1 in the TIM file format, which |
|||
is a very simple image format designed specifically for the PS1 as it can |
|||
hold X and Y coordinates for either image and CLUT data which are used as |
|||
target coordinates when uploading the texture to VRAM. TIM files are typically |
|||
created from regular image files (bmp, pcx, jpeg or bmp) with tools such as |
|||
<b>timtool</b> included in the PsyQ/Programmer Tool SDK, |
|||
<a href="https://github.com/lameguy64/img2tim">img2tim</a> which is a free |
|||
command-line driven TIM converter and finally, |
|||
<a href="https://github.com/lameguy64/timedit">timedit</a> which is essentially |
|||
a free albeit slightly dodgy equivalent of <b>timtool</b>. |
|||
</p> |
|||
<p> |
|||
For beginners it may be best to use <b>timedit</b> as its the only free tool |
|||
(or at the very least one that I'm aware of) that features a graphical preview |
|||
of the TIM image layout in VRAM or stick to <b>timtool</b> if you're using the |
|||
PsyQ/Programmers Tool SDK. |
|||
</p> |
|||
|
|||
<h2 id="cluts">Color Look-up Tables (CLUT)</h2> |
|||
<p> |
|||
A CLUT is simply a 16x1 or 256x1 16-bit pixel image that normally accompanies |
|||
4-bit and 8-bit texture images respectively. If you haven't guessed by now, a |
|||
CLUT is essentially the color palette of the image it accompanies, where each |
|||
pixel of the CLUT represents a 16-bit color entry for the texture image |
|||
starting from the left (ie. the first pixel from the left represents the color |
|||
for index 0 while the very last pixel of the CLUT represents the color for |
|||
index 15 or index 255). CLUTs are normally used with 4-bit and 8-bit texture |
|||
images, though it can also be used for procedurally generated textures such as |
|||
animated plasma effects. |
|||
</p> |
|||
<p> |
|||
The TIM file format could support multiple CLUTs on a single TIM file, |
|||
as the CLUT headers in the file format allow for more than 1 pixel high |
|||
CLUTs. This is beyond the scope of this part of the tutorial series however. |
|||
</p> |
|||
|
|||
<h2 id="texaddr">Texture Addressing on the PS1</h2> |
|||
<p> |
|||
You may have learned from the last tutorial that the PS1 accesses the VRAM |
|||
as a two-dimensional image rather than a more conventional linear framebuffer. |
|||
Well, this also applies on how textures in VRAM are 'selected' for drawing with |
|||
textured primitives. |
|||
</p> |
|||
<p> |
|||
The PS1 addresses the VRAM in pages, in which the VRAM is divided into a |
|||
grid of 16x2 cells of 64x256 16-bit pixels each. The actual texture page |
|||
coordinates are still X,Y but with a 64x256 granularity instead. The image |
|||
below visually illustrates the cells of each texture page. |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/vram-texture-pages.svg"> |
|||
<i>Texture page grid of the VRAM</i> |
|||
</center> |
|||
<p> |
|||
Texture pages only applies to the selection of the area at which textures would |
|||
be read from by textured graphics primitives, as VRAM coordinates of display |
|||
and drawing environments do not adhere to this texture page granularity at all. |
|||
Setting a texture page serves as an anchor point at which textured primitives |
|||
would source texture data from starting from the top-left corner of the texture |
|||
page, with the U,V coordinates of the primitive serving as an offset relative to |
|||
the current texture page allowing small portions of a texture page to be read |
|||
and drawn, such as animation frames of one particular character in a large |
|||
sprite sheet. |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/page-texcoord-relation.svg"> |
|||
<i>An example of using U,V coordinates to select a particular sprite (in this |
|||
case at 48,32) in a sprite sheet</i> |
|||
</center> |
|||
<p> |
|||
Of course this would mean that the texture images would have to be arranged |
|||
such that it is placed on the top-right corner of a texture page boundary for |
|||
the U,V coordinates to make the most sense. However, some simple offset |
|||
translation based on the texture image's position relative to the page boundary |
|||
should get around that issue and is going to be covered in this chapter. |
|||
</p> |
|||
<p> |
|||
One thing to consider about texture coordinates that may initially confuse |
|||
beginners is that while the width of a 4-bit and 8-bit texture on VRAM varies |
|||
from the actual width of the image itself, the texture coordinates does not |
|||
need to be adjusted to take that into account as long as the correct color |
|||
depth is specified in the texture page value. In this case, if you want to |
|||
draw a texture at 96,24 from a 256x256 4-bit texture sheet, you just simply |
|||
specify a U,V coordinate of 96,24 in your primitive as if the texture were |
|||
still 16-bit. |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/vram-texture-coordinates.svg"> |
|||
<i>Texture coordinates are always true to the actual size of the |
|||
texture image</i> |
|||
</center> |
|||
<p> |
|||
And because the U,V coordinates only have a range of 0-255, it is not possible |
|||
to draw a texture image larger than 256x256 pixels regardless of color depth. |
|||
To draw larger textures one has to draw multiple primitives to span the entire |
|||
size of a larger image, trying to draw a SPRT primitive with a size greater |
|||
than 256x256 will only result in a wrap around. |
|||
</p> |
|||
|
|||
<h2 id="seltexpage">Defining and Selecting a Texture Page</h2> |
|||
<p> |
|||
A texture page value is easily defined using the <b>getTPage()</b> macro. |
|||
A function version of this macro is present in the PsyQ/Programmers Tool SDK |
|||
as <b>GetTPage()</b>, but this is not available in PSn00bSDK as it would be |
|||
considered redundant. |
|||
</p> |
|||
<pre>tpage = getTPage( <i>tp</i>, <i>abr</i>, <i>x</i>, <i>y</i> ); |
|||
</pre> |
|||
<p> |
|||
<i>tp</i> specifies the color depth for the texture page in the range of |
|||
0 to 2 (0:4-bit, 1:8-bit, 2:16-bit). <i>abr</i> specifies the blend operator |
|||
for both non-textured and textured semi-transparent primitives which can be |
|||
ignored for now and lastly, <i>x,y</i> specifies the X,Y coordinates of the |
|||
VRAM in 16-bit pixel units. Keep in mind that the coordinates will be rounded |
|||
down to the next lowest texture page. |
|||
</p> |
|||
<p> |
|||
Now that a texture page value has been defined, there are a number of ways to |
|||
set it to the GPU. One is through the <i>tpage</i> field of the <b>DRAWENV</b> |
|||
struct which specifies the initial texture page value whenever the drawing |
|||
environment is applied. Another is to use a <b>DR_TPAGE</b> primitive which |
|||
can be defined with the <b>setDrawTPage()</b> macro which follows the same |
|||
syntax as <b>getTPage()</b>. <b>DR_TPAGE</b> is needed for <b>SPRT</b> |
|||
primitives which lack a tpage field, though it is also useful for non-textured |
|||
primitives to set the blend operator for semi-transparent primitives. |
|||
</p> |
|||
<p> |
|||
Because the PS1 usually processes primitives that have been sorted last first, |
|||
<b>DR_TPAGE</b> primitives must be sorted after <b>SPRT</b> or other similar |
|||
primitives have been sorted. |
|||
</p> |
|||
<p> |
|||
The following table describes the bit fields of a texture page value which may |
|||
come in handy for the more crafty programmers. |
|||
</p> |
|||
<center> |
|||
<table class="bordered-table"> |
|||
<tbody><tr> |
|||
<th>Bits</th> |
|||
<td>15-14</td> |
|||
<td>13</td> |
|||
<td>12</td> |
|||
<td>11</td> |
|||
<td>10</td> |
|||
<td>9</td> |
|||
<td>8-7</td> |
|||
<td>6-5</td> |
|||
<td>4</td> |
|||
<td>3-0</td> |
|||
</tr> |
|||
<tr> |
|||
<th>Description</th> |
|||
<td>Reserved</td> |
|||
<td>Y-flip*</td> |
|||
<td>X-flip*</td> |
|||
<td>Texture disable*</td> |
|||
<td>Draw on displayed area</td> |
|||
<td>Dither enable</td> |
|||
<td>Texture color depth</td> |
|||
<td>Blend operator</td> |
|||
<td>Texture page Y (n*256)</td> |
|||
<td>Texutre page X (n*64)</td> |
|||
</tr> |
|||
<tr> |
|||
<th colspan="11">*Does not work on <i>really</i> early units, not recommended |
|||
to use to maintain compatibility</th> |
|||
</tr> |
|||
</tbody></table> |
|||
</center> |
|||
<p> |
|||
Whilst on the topic of texture page selection, when working with 4-bit and |
|||
8-bit texture images you will also need to use <b>getClut()</b> to define a |
|||
CLUT value and is required for 4-bit and 8-bit texture images to draw properly. |
|||
Obviously this is not required for 16-bit texture images. |
|||
</p> |
|||
<pre>clut = getClut( <i>x</i>, <i>y</i> ); |
|||
</pre> |
|||
<p> |
|||
<i>x,y</i> specifies the X,Y coordinate of the CLUT within the VRAM. |
|||
However, keep in mind that the X axis must be a multiple to 16 pixels for a |
|||
CLUT to be defined correctly as otherwise it will be rounded down to the |
|||
lowest CLUT value. |
|||
</p> |
|||
<p> |
|||
As for selecting the CLUT, all textured primitives usually have a <i>clut</i> |
|||
field in the struct in which the CLUT value can be set to. There is also a |
|||
<b>setClut()</b> macro for setting CLUT coordinates to a primitive directly. |
|||
</p> |
|||
<p> |
|||
Usually, the coordinates for texture page and CLUT values are typically derived |
|||
from the X,Y coordinates of the TIM image file to take into account TIM images |
|||
that are not placed on the top-left corner of the texture page boundary. |
|||
</p> |
|||
<p> |
|||
The following describes the bit fields of a CLUT value. |
|||
</p> |
|||
<center> |
|||
<table class="bordered-table"> |
|||
<tbody><tr> |
|||
<th>Bits</th> |
|||
<td>15</td> |
|||
<td>14-6</td> |
|||
<td>5-0</td> |
|||
</tr> |
|||
<tr> |
|||
<th>Description</th> |
|||
<td>Reserved</td> |
|||
<td>Y coordinate</td> |
|||
<td>X coordinate (n*16)</td> |
|||
</tr> |
|||
</tbody></table> |
|||
</center> |
|||
|
|||
<h2 id="maketexture">Creating a TIM Texture Image</h2> |
|||
<p> |
|||
There are numerous ways to convert image files into the TIM format, the most |
|||
common is by using <b>timtool</b> from the official PsyQ/Programmers Tool SDKs, |
|||
or at least those who chose to use that SDK. Another is to use my free but old |
|||
command-line converter called <b>img2tim</b>, which follows the same command |
|||
line syntax as <b>bmp2tim</b> but supports many more image formats supported |
|||
by the FreeImage library and has better conversion options related to |
|||
transparencies. |
|||
</p> |
|||
<p> |
|||
Perhaps the most preferable tool to use for those who've stuck to using |
|||
PSn00bSDK is <b>timedit</b>, as not only is it free but also features a |
|||
similar graphical interface to <b>timtool</b>, on top of extra features |
|||
useful for managing a large amount of TIM images, such as grouping. |
|||
</p> |
|||
<p> |
|||
Whichever tool you use, convert the image below into a 8-bit TIM file with |
|||
image coordinates of 640,0 and CLUT coordinates of 0,480. You will have to |
|||
convert it into a 4-bit or 8-bit TIM as this tutorial is also going to cover |
|||
how to work with CLUTs. |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/texture64.png"> |
|||
</center> |
|||
<p> |
|||
When converting the image, always remember that texture image and CLUT |
|||
coordinates in the tools are always absolute coordinates to the VRAM |
|||
regardless of color depth. And in case you're wondering, the PS1 cannot |
|||
use 24-bit TIM images, as the GPU can only draw graphics in 16-bit color |
|||
depth but can display 24-bit images by entering 24-bit color mode, but |
|||
this is beyond the scope of this chapter. |
|||
</p> |
|||
|
|||
<h2 id="inctexture">Including TIM Image Data</h2> |
|||
<p> |
|||
In the meantime, the easiest way to include a binary file into your program |
|||
is to include it as an object file by means of a very simple assembler file, |
|||
and access that file as an array by defining its symbol name with <h>extern</h>. |
|||
Its not ideal for larger projects, but this will do the job for testing purposes. |
|||
</p> |
|||
<h3>PsyQ/Programmers Tool SDK</h3> |
|||
<p> |
|||
Save the following as <h>my_image.asm</h>. |
|||
</p> |
|||
<pre> opt m+,l.,c+ |
|||
|
|||
section data ; Store the array in the data section |
|||
|
|||
global tim_my_image ; Define label as global |
|||
tim_my_image: |
|||
incbin 'my_image.tim' ; Include file data (your TIM) |
|||
</pre> |
|||
<p> |
|||
The name of the data is defined by the label, in this case <h>tim_my_image</h>. |
|||
Make sure the label is also defined by a global directive so the linker can find |
|||
it when linked against your C program. When writing the assembler file, make sure |
|||
line indentations are created with real TAB characters as ASMPSX will throw an |
|||
error otherwise. |
|||
</p> |
|||
<p> |
|||
Assemble the file using <h>ASMPSX</h> to turn it into an object file. |
|||
</p> |
|||
<pre>asmpsx /l my_image.asm,my_image.obj |
|||
</pre> |
|||
<p>Then link it with your program by simply specifying the object file.</p> |
|||
<pre>ccpsx -O2 -Xm -Xo$80010000 my_image.obj program.c -o program.cpe |
|||
</pre> |
|||
<h3>PSn00bSDK</h3> |
|||
<p> |
|||
In PSn00bSDK, it works in much the same principle as in the PsyQ SDK, |
|||
but this one will be written in GNU assembler syntax. Save the assembler |
|||
file with a <h>.s</h> file extension. |
|||
</p> |
|||
<pre>.section .data |
|||
|
|||
.global tim_my_image |
|||
.type tim_my_image, @object |
|||
tim_my_image: |
|||
.incbin "my_image.tim" |
|||
</pre> |
|||
<p> |
|||
It is recommended to use the makefile from one of the example programs included |
|||
with PSn00bSDK, as it has parameters for building with assembler files already |
|||
defined and should automatically pick your assembler file as long as it has |
|||
a <h>.s</h> file extension. |
|||
</p> |
|||
<h3>Accessing the Array</h3> |
|||
<p> |
|||
On both SDKs, the binary file can be accessed as an array by simply defining |
|||
it with an <h>extern</h>. Make sure the name matches with the label name defined |
|||
in the assembler file. |
|||
</p> |
|||
<pre>extern int tim_my_image[]; |
|||
</pre> |
|||
<p> |
|||
If you get mismatching type errors when compiling, you can simply cast it with a |
|||
different pointer type with <h>(u_long*)</h> or <h>(u_int*)</h> depending on |
|||
the compiler warnings you're getting. <h>u_int</h> is typically used in PSn00bSDK |
|||
instead of <h>u_long</h> as modern GCC interprets <h>u_long</h> as a 64-bit integer |
|||
whereas it is a 32-bit integer in PsyQ. |
|||
</p> |
|||
|
|||
<h2>Parsing and Uploading the TIM to VRAM</h2> |
|||
<p> |
|||
To parse a TIM image file, use <b>OpenTIM()</b> to set the TIM file data for |
|||
parsing and <b>ReadTIM()</b> to retrieve header information of the TIM file to |
|||
a <b>TIM_IMAGE</b> struct. The <b>TIM_IMAGE</b> would contain not only a pointer |
|||
to the X,Y and size coordinates of either texture image and CLUT but also |
|||
pointers to the image and CLUT data within the TIM file. |
|||
</p> |
|||
<p> |
|||
In PSn00bSDK, <b>GetTimInfo()</b> function instead. It still returns the same |
|||
<b>TIM_IMAGE</b> struct. |
|||
</p> |
|||
<p> |
|||
The TIM image coordinates are in the <i>*prect</i> field and CLUT in |
|||
the <i>*crect</i> field, both are of type RECT. The actual texture image data |
|||
is at <i>*paddr</i> and the CLUT data at <i>*caddr</i>. The color depth of |
|||
the TIM file are in bits 0-3 of the <i>mode</i> field and CLUT presence is |
|||
determined by testing bit 4. |
|||
</p> |
|||
<p> |
|||
Uploading either pixel or CLUT data is done using <b>LoadImage()</b>, followed |
|||
by a call to <b>DrawSync()</b> to wait for texture upload to complete. Whilst |
|||
you might be able to get away with not waiting for the texture upload to |
|||
finish processing, it is recommended to wait for upload completion as |
|||
unpredictable results may occur otherwise. |
|||
</p> |
|||
<p> |
|||
The TIM image upload function should go like this. |
|||
</p> |
|||
<pre>void LoadTexture(u_long *tim, TIM_IMAGE *tparam) { |
|||
|
|||
// Read TIM information (PsyQ) |
|||
OpenTIM(tim); |
|||
ReadTIM(tparam); |
|||
|
|||
// Read TIM information (PSn00bSDK) |
|||
//GetTimInfo(tim, tparam); |
|||
|
|||
// Upload pixel data to framebuffer |
|||
LoadImage(tparam->prect, (u_long*)tparam->paddr); |
|||
DrawSync(0); |
|||
|
|||
// Upload CLUT to framebuffer if present |
|||
if( tparam->mode & 0x8 ) { |
|||
|
|||
LoadImage(tparam->crect, (u_long*)tparam->caddr); |
|||
DrawSync(0); |
|||
|
|||
} |
|||
|
|||
} |
|||
</pre> |
|||
<p> |
|||
In PSn00bSDK, you may additionally replace u_long to u_int. They are actually |
|||
the same in PsyQ/Programmers Tool whereas in modern GCC/PSn00bSDK u_long |
|||
usually defines a 64-bit unsigned integer. |
|||
</p> |
|||
<p> |
|||
Now that you have a TIM upload function, the TIM loading sequence should go like so. |
|||
</p> |
|||
<pre>extern int tim_my_image[]; |
|||
|
|||
// To keep a copy of the TIM coordinates for later |
|||
int tim_mode; |
|||
RECT tim_prect,tim_crect; |
|||
|
|||
.. |
|||
|
|||
void LoadStuff(void) { |
|||
|
|||
// This can be defined locally, if you don't need the TIM coordinates |
|||
TIM_IMAGE my_image; |
|||
|
|||
// Load the TIM |
|||
LoadTexture((u_long*)tim_my_image, &my_image); |
|||
|
|||
// Copy the TIM coordinates |
|||
tim_prect = *my_image.prect; |
|||
tim_crect = *my_image.crect; |
|||
tim_mode = my_image.mode; |
|||
|
|||
} |
|||
</pre> |
|||
<p> |
|||
Reason you may want to keep a copy of the TIM coordinates separate from the |
|||
<b>TIM_IMAGE</b> variable is that once you've figured out how to load files |
|||
from CD and load the TIM file to a dynamically allocated buffer, relying on |
|||
the <b>TIM_IMAGE</b> struct may not be a good idea as the <i>*prect</i> and |
|||
<i>*crect</i> fields point to the TIM file data directly, and will most |
|||
likely become undefined data once you've finished uploading that TIM to |
|||
VRAM and deallocated its buffer in later parts of your program. |
|||
</p> |
|||
|
|||
<h2>Drawing the TIM</h2> |
|||
<p> |
|||
Now that a texture image has been loaded. The next thing to do is to set |
|||
it's texture page to the drawing environment. Since there's only one texture |
|||
to deal with, the texture page can be set to the <b>DRAWENV</b> struct. |
|||
</p> |
|||
<pre>draw[0].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
draw[1].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
</pre> |
|||
<p> |
|||
To deal with TIMs that are not page aligned, the U,V offset relative to |
|||
the TIM's rounded down texture page can be determined with the following |
|||
and should work for texture images of any color depth. |
|||
</p> |
|||
<pre>int tim_uoffs,tim_voffs; |
|||
|
|||
tim_uoffs = (tim_prect.x%64)<<(2-(tim_mode&0x3)); |
|||
tim_voffs = (tim_prect.y&0xff); |
|||
</pre> |
|||
<p> |
|||
Whilst this would allow texture images to not require being aligned to the |
|||
top-left corner of the texture page boundary, texture images cannot cross |
|||
between the vertical texture page bounds and for 4-bit texture images, |
|||
should not cross the horizontal texture page bounds as otherwise trying to |
|||
draw the texture image with a <b>SPRT</b> will result in wrapping in |
|||
relation to the texture page. |
|||
</p> |
|||
<p> |
|||
Now to actually draw the texture image. This can be done with a <b>SPRT</b> |
|||
primitive which simply draws a textured sprite of a specified size. It doesn't |
|||
do fancy things such as rotation and scaling but its a useful primitive for |
|||
drawing simple sprites. |
|||
</p> |
|||
<pre>SPRT *sprt; |
|||
|
|||
... |
|||
|
|||
sprt = (SPRT*)nextpri; |
|||
|
|||
setSprt(sprt); // Initialize the primitive (important) |
|||
setXY0(sprt, 48, 48); // Position the sprite at (48,48) |
|||
setWH(sprt, 64, 64); // Set sprite size to 64x64 pixels |
|||
setUV0(sprt, // Set UV coordinates from TIM offsets |
|||
tim_uoffs, |
|||
tim_voffs); |
|||
setClut(sprt, // Set CLUT coordinates from TIM to sprite |
|||
tim_crect.x, |
|||
tim_crect.y); |
|||
setRGB0(sprt, // Set color of sprite, 128 is neutral |
|||
128, 128, 128); |
|||
|
|||
addPrim(ot[db], sprt); // Sort primitive to OT |
|||
nextpri += sizeof(SPRT); // Advance next primitive |
|||
</pre> |
|||
<p> |
|||
When dealing with multiple texture images that tend to reside on different |
|||
texture pages, you will have to sort a <b>DR_TPAGE</b> primitive right after |
|||
the <b>SPRT</b> primitive that requires a particular texture page value set, |
|||
as the PS1 processes primitives that are sorted last first. |
|||
</p> |
|||
<p> |
|||
Whilst not required in this chapter, this is how you sort a <b>DR_TPAGE</b> |
|||
for when you start playing around with more texture images. |
|||
</p> |
|||
<pre>DR_TPAGE *tpage; |
|||
|
|||
... |
|||
|
|||
tpage = (DR_TPAGE*)nextpri; |
|||
|
|||
setDrawTPage(tpage, 0, 1, // Set TPage primitive |
|||
getTPage(my_image.mode&0x3, 0, |
|||
my_image.prect->x, my_image.prect->y)); |
|||
|
|||
addPrim(ot[db], tpage); // Sort primitive to OT |
|||
|
|||
nextpri += sizeof(DR_TPAGE); // Advance next primitive address |
|||
</pre> |
|||
<p> |
|||
A very simple optimization practice you may want to consider when you start |
|||
getting into larger projects is that you only need to sort one <b>DR_TPAGE</b> |
|||
primitive if all the sprites sorted prior share a common texture page. |
|||
</p> |
|||
|
|||
<h2>Sample Code</h2> |
|||
<p> |
|||
Working from code in the last tutorial, here's what the code should |
|||
look like: |
|||
</p> |
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <libetc.h> // Includes some functions that controls the display |
|||
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <libgpu.h> // GPU library header |
|||
|
|||
#define OTLEN 8 // Ordering table length (recommended to set as a define |
|||
// so it can be changed easily) |
|||
|
|||
DISPENV disp[2]; // Display/drawing buffer parameters |
|||
DRAWENV draw[2]; |
|||
int db = 0; |
|||
|
|||
// PSn00bSDK requires having all u_long types replaced with |
|||
// u_int, as u_long in modern GCC that PSn00bSDK uses defines it as a 64-bit integer. |
|||
|
|||
u_long ot[2][OTLEN]; // Ordering table length |
|||
char pribuff[2][32768]; // Primitive buffer |
|||
char *nextpri; // Next primitive pointer |
|||
|
|||
int tim_mode; // TIM image parameters |
|||
RECT tim_prect,tim_crect; |
|||
int tim_uoffs,tim_voffs; |
|||
|
|||
void display() { |
|||
|
|||
DrawSync(0); // Wait for any graphics processing to finish |
|||
|
|||
VSync(0); // Wait for vertical retrace |
|||
|
|||
PutDispEnv(&disp[db]); // Apply the DISPENV/DRAWENVs |
|||
PutDrawEnv(&draw[db]); |
|||
|
|||
SetDispMask(1); // Enable the display |
|||
|
|||
DrawOTag(ot[db]+OTLEN-1); // Draw the ordering table |
|||
|
|||
db = !db; // Swap buffers on every pass (alternates between 1 and 0) |
|||
nextpri = pribuff[db]; // Reset next primitive pointer |
|||
|
|||
} |
|||
|
|||
// Texture upload function |
|||
void LoadTexture(u_long *tim, TIM_IMAGE *tparam) { |
|||
|
|||
// Read TIM parameters (PsyQ) |
|||
OpenTIM(tim); |
|||
ReadTIM(tparam); |
|||
|
|||
// Read TIM parameters (PSn00bSDK) |
|||
//GetTimInfo(tim, tparam); |
|||
|
|||
// Upload pixel data to framebuffer |
|||
LoadImage(tparam->prect, (u_long*)tparam->paddr); |
|||
DrawSync(0); |
|||
|
|||
// Upload CLUT to framebuffer if present |
|||
if( tparam->mode & 0x8 ) { |
|||
|
|||
LoadImage(tparam->crect, (u_long*)tparam->caddr); |
|||
DrawSync(0); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
void loadstuff(void) { |
|||
|
|||
TIM_IMAGE my_image; // TIM image parameters |
|||
|
|||
extern u_long tim_my_image[]; |
|||
|
|||
// Load the texture |
|||
LoadTexture(tim_my_image, &my_image); |
|||
|
|||
// Copy the TIM coordinates |
|||
tim_prect = *my_image.prect; |
|||
tim_crect = *my_image.crect; |
|||
tim_mode = my_image.mode; |
|||
|
|||
// Calculate U,V offset for TIMs that are not page aligned |
|||
tim_uoffs = (tim_prect.x%64)<<(2-(tim_mode&0x3)); |
|||
tim_voffs = (tim_prect.y&0xff); |
|||
|
|||
} |
|||
|
|||
// To make main look tidy, init stuff has to be moved here |
|||
void init(void) { |
|||
|
|||
// Reset graphics |
|||
ResetGraph(0); |
|||
|
|||
// First buffer |
|||
SetDefDispEnv(&disp[0], 0, 0, 320, 240); |
|||
SetDefDrawEnv(&draw[0], 0, 240, 320, 240); |
|||
// Second buffer |
|||
SetDefDispEnv(&disp[1], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw[1], 0, 0, 320, 240); |
|||
|
|||
draw[0].isbg = 1; // Enable clear |
|||
setRGB0(&draw[0], 63, 0, 127); // Set clear color (dark purple) |
|||
draw[1].isbg = 1; |
|||
setRGB0(&draw[1], 63, 0, 127); |
|||
|
|||
nextpri = pribuff[0]; // Set initial primitive pointer address |
|||
|
|||
// load textures and possibly other stuff |
|||
loadstuff(); |
|||
|
|||
// set tpage of lone texture as initial tpage |
|||
draw[0].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
draw[1].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
|
|||
// apply initial drawing environment |
|||
PutDrawEnv(&draw[!db]); |
|||
|
|||
} |
|||
|
|||
int main() { |
|||
|
|||
TILE *tile; // Pointer for TILE |
|||
SPRT *sprt; // Pointer for SPRT |
|||
|
|||
// Init stuff |
|||
init(); |
|||
|
|||
while(1) { |
|||
|
|||
ClearOTagR(ot[db], OTLEN); // Clear ordering table |
|||
|
|||
// Sort textured sprite |
|||
|
|||
sprt = (SPRT*)nextpri; |
|||
|
|||
setSprt(sprt); // Initialize the primitive (very important) |
|||
setXY0(sprt, 48, 48); // Position the sprite at (48,48) |
|||
setWH(sprt, 64, 64); // Set size to 64x64 pixels |
|||
setUV0(sprt, // Set UV coordinates |
|||
tim_uoffs, |
|||
tim_voffs); |
|||
setClut(sprt, // Set CLUT coordinates to sprite |
|||
tim_crect.x, |
|||
tim_crect.y); |
|||
setRGB0(sprt, // Set primitive color |
|||
128, 128, 128); |
|||
addPrim(ot[db], sprt); // Sort primitive to OT |
|||
|
|||
nextpri += sizeof(SPRT); // Advance next primitive address |
|||
|
|||
|
|||
// Sort untextured tile primitive from the last tutorial |
|||
|
|||
tile = (TILE*)nextpri; // Cast next primitive |
|||
|
|||
setTile(tile); // Initialize the primitive (very important) |
|||
setXY0(tile, 32, 32); // Set primitive (x,y) position |
|||
setWH(tile, 64, 64); // Set primitive size |
|||
setRGB0(tile, 255, 255, 0); // Set color yellow |
|||
addPrim(ot[db], tile); // Add primitive to the ordering table |
|||
|
|||
nextpri += sizeof(TILE); // Advance the next primitive pointer |
|||
|
|||
|
|||
// Update the display |
|||
display(); |
|||
|
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
<p> |
|||
Compile the example, run it and you should get a yellow square cascaded by |
|||
a sprite with your texture image. |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/3-textures.png"> |
|||
</center> |
|||
<p> |
|||
You may notice that the untextured rectangle is drawn before the textured |
|||
sprite even though the textured sprite was sorted first and the untextured |
|||
rectangle last. That's because of the way how primitives are appended to |
|||
the ordering table in <b>addPrim()</b>, where the primitive being sorted |
|||
is linked right after a primitive that has been sorted to it previously, |
|||
and the PS1 hardware parses the ordering table from the top of the array |
|||
to the bottom with a reverse ordering table (created with <b>ClearOTagR()</b>). |
|||
</p> |
|||
<center> |
|||
<img src="Chapter%201.3%20Textures,%20TPages%20and%20CLUTs_files/ordertable-multiprims.svg"> |
|||
<i>How primitives are <b>appended</b> to a preoccupied ordering table entry</i> |
|||
</center> |
|||
<p> |
|||
Primitive 1 would be the <b>SPRT</b> primitive, Primitive 2 would be the |
|||
<b>DR_TPAGE</b> primitive (if there was) and lastly, Primitive 3 would be |
|||
the untextured <b>TILE</b> primitive. You may think that a reverse |
|||
order ordering table makes no sense at first, but this technique is |
|||
integral to the PS1's ability to do on-the-fly sorting of polygons when |
|||
rendering 3D graphics. |
|||
</p> |
|||
|
|||
<h2 id="tipsandtricks">Tips, Tricks and Improvements</h2> |
|||
<h3>Pre-calculate tpage, CLUT and UV offset in a struct</h3> |
|||
<p> |
|||
Using <b>getTPage()</b>, <b>getClut()</b> and <b>setClut()</b> macros on |
|||
every sprite sorted isn't exactly the most efficient way of doing things |
|||
especially when drawing lots of sprites, not to mention makes your code |
|||
look cluttered when managing several TIM images at once. This can be |
|||
addressed by defining a struct that contains all the parameters you |
|||
need precomputed for drawing a sprite. |
|||
</p> |
|||
<pre>typedef struct _SPRITE { |
|||
u_short tpage; // Tpage value |
|||
u_short clut; // CLUT value |
|||
u_char u,v; // UV offset (useful for non page aligned TIMs) |
|||
u_char w,h; // Size (primitives can only draw 256x256 anyway) |
|||
CVECTOR col; |
|||
} SPRITE; |
|||
|
|||
... |
|||
|
|||
// Sets parameters to a MYSPRITE using coordinates from TIM_INFO |
|||
|
|||
void GetSprite(TIM_IMAGE *tim, SPRITE *sprite) { |
|||
|
|||
// Get tpage value |
|||
sprite->tpage = getTPage(tim->mode&0x3, 0, |
|||
tim->prect->x, tim->prect->y); |
|||
|
|||
// Get CLUT value |
|||
if( tim->mode & 0x8 ) { |
|||
sprite->clut = getClut(tim->crect->x, tim->crect->y); |
|||
} |
|||
|
|||
// Set sprite size |
|||
sprite->w = tim->prect->w<<(2-tim->mode&0x3); |
|||
sprite->h = tim->prect->h; |
|||
|
|||
// Set UV offset |
|||
sprite->u = (tim->prect->x&0x3f)<<(2-tim->mode&0x3); |
|||
sprite->v = tim->prect->y&0xff; |
|||
|
|||
// Set neutral color |
|||
sprite->col.r = 128; |
|||
sprite->col.g = 128; |
|||
sprite->col.b = 128; |
|||
|
|||
} |
|||
</pre> |
|||
<p>And to draw the sprite, you can write a simple function for it:</p> |
|||
<pre>char *SortSprite(int x, int y, u_long *ot, char *pri, SPRITE *sprite) { |
|||
|
|||
SPRT *sprt; |
|||
DR_TPAGE *tpage; |
|||
|
|||
sprt = (SPRT*)pri; // initialize the sprite |
|||
setSprt(sprt); |
|||
|
|||
setXY0(sprt, x, y); // Set position |
|||
setWH(sprt, sprite->w, sprite->h); // Set size |
|||
setUV0(sprt, sprite->u, sprite->v); // Set UV coordinate of sprite |
|||
setRGB0(sprt, // Set the color |
|||
sprite->col.r, |
|||
sprite->col.g, |
|||
sprite->col.b); |
|||
sprt->clut = sprite->clut; // Set the CLUT value |
|||
|
|||
addPrim(ot, sprt); // Sort the primitive and advance |
|||
pri += sizeof(SPRT); |
|||
|
|||
tpage = (DR_TPAGE*)pri; // Sort the texture page value |
|||
setDrawTPage(tpage, 0, 1, sprite->tpage); |
|||
addPrim(ot, tpage); |
|||
|
|||
return pri+sizeof(DR_TPAGE); // Return new primitive pointer |
|||
// (set to nextpri) |
|||
|
|||
} |
|||
</pre> |
|||
<p> |
|||
This method will also work for sprite sheets by simply modifying the |
|||
GetSprite() function mentioned earlier such that you can specify an U,V |
|||
offset relative to the TIM's U,V offset and the size of the sprite. |
|||
</p> |
|||
|
|||
<h3>Use Sprite Sheets</h3> |
|||
<p> |
|||
Instead of creating a single TIM image for each and every animation frame |
|||
of your character sprite, it is best to compile such small images as one |
|||
large image. This is called a sprite sheet and allows all sprite frames |
|||
to share a common palette if you use 4-bit or 8-bit color depth. If all |
|||
sprite frames have the same size, arrange the sprites in a grid where |
|||
each cell is the same size as the sprites. This way you can compute the |
|||
U,V coordinate of the sprites in the grid easily. |
|||
</p> |
|||
|
|||
<h3>Lower color depth textures are faster</h3> |
|||
<p> |
|||
A 4-bit texture is faster to draw than a 8-bit texture, and a 8-bit |
|||
texture is faster to draw than a 16-bit texture, as the GPU has to read |
|||
less data from VRAM when drawing textures of lower color depth. Find a |
|||
balance that achieves best possible performance without degrading the |
|||
quality of your sprites or texture images too much. |
|||
</p> |
|||
|
|||
<h3>SPRT_8 and SPRT_16 are faster than SPRT</h3> |
|||
<p> |
|||
The fixed size sprite primitives are a bit faster than <b>SPRT</b> |
|||
primitives, making them best suited for particle sprites of a fixed size |
|||
or when drawing tiles of a 2D map. |
|||
</p> |
|||
|
|||
<h3>Minimize tpage primitive changes</h3> |
|||
<p> |
|||
This technique is most applicable when drawing tile maps. If your tile |
|||
sheet fits in a single texture page (less than 256x256), you only have |
|||
to sort a single <b>DR_TPAGE</b> primitive for all the tiles. This may |
|||
also help the GPU maintain texture cache coherency, as well as minimizing |
|||
redundant primitive packets.</p> |
|||
<h3>Textures don't need to be powers of two</h3> |
|||
<p> |
|||
Texutures of any size can be used by the GPU, though it is recommended to |
|||
make the width of 8-bit TIMs a multiples of 2 and multiples of 4 for 4-bit |
|||
TIMs as mentioned earlier in this chapter. |
|||
</p> |
|||
|
|||
<h2 id="conclusion">Conclusion</h2> |
|||
<p> |
|||
This concludes Chapter 1.3. of Lameguy64's PSX Tutorial series. If you've |
|||
sifted though this chapter well enough, you should have figured out how to |
|||
handle TIM images, uploading them to VRAM and drawing them. |
|||
</p> |
|||
<p>A few things you may want to experiment with for further learning:</p> |
|||
<ul> |
|||
<li>Try loading more TIMs and drawing them as individual sprites. Make sure |
|||
the TIM image and CLUT do not overlap one another in the TIM editing tool |
|||
you're using.</li> |
|||
</ul> |
|||
|
|||
<hr> |
|||
<table width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left"><a href="http://lameguy64.net/tutorials/pstutorials/chapter1/2-graphics.html">Previous</a></td> |
|||
<td width="20%" align="center"><a href="http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"><a href="http://lameguy64.net/tutorials/pstutorials/chapter1/4-controllers.html">Next</a></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
|
|||
</body></html> |
|||
@ -0,0 +1,705 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="420" |
|||
height="220" |
|||
viewBox="0 0 111.125 58.208337" |
|||
version="1.1" |
|||
id="svg8" |
|||
sodipodi:docname="ordertable-multiprims.svg" |
|||
inkscape:version="0.92.1 r15371"> |
|||
<defs |
|||
id="defs2"> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker7807" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path7805" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker7561" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path7559" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6581" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path6579" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker6049" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path6047" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5905" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path5903" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9889" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9871" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.4,0,0,-0.4,-4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker9806" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path9804" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker6984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path6982" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5944" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path5942" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5328" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5326" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5883" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5881" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker5705" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="Arrow2Mstart"> |
|||
<path |
|||
transform="scale(0.6)" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
id="path5703" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mstart" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mstart" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4561" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(0.4,0,0,0.4,4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Send" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Send" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path4570" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4984" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4982" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker13622" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path13620" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4575" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4573" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4587" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4585" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4593" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM" |
|||
inkscape:collect="always"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4591" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:isstock="true" |
|||
style="overflow:visible" |
|||
id="marker4599" |
|||
refX="0" |
|||
refY="0" |
|||
orient="auto" |
|||
inkscape:stockid="TriangleInM"> |
|||
<path |
|||
transform="scale(-0.4)" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
id="path4597" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="TriangleInM" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker4605" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true" |
|||
inkscape:collect="always"> |
|||
<path |
|||
id="path4603" |
|||
d="M 5.77,0 -2.88,5 V -5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="scale(-0.4)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
</defs> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1" |
|||
inkscape:cx="298.22087" |
|||
inkscape:cy="212.17404" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="false" |
|||
units="px" |
|||
inkscape:snap-bbox="false" |
|||
inkscape:snap-bbox-edge-midpoints="true" |
|||
inkscape:snap-nodes="true" |
|||
inkscape:snap-others="true" |
|||
inkscape:object-nodes="true" |
|||
inkscape:snap-midpoints="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:bbox-nodes="false" |
|||
inkscape:object-paths="true" |
|||
inkscape:snap-global="true" |
|||
inkscape:snap-text-baseline="true"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-512,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,135.46666" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,135.46666" |
|||
orientation="512,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
<inkscape:grid |
|||
type="xygrid" |
|||
id="grid5333" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title></dc:title> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-238.79163)"> |
|||
<text |
|||
id="text7984" |
|||
y="267.10205" |
|||
x="85.989586" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="267.10205" |
|||
x="85.989586" |
|||
id="tspan7982" |
|||
sodipodi:role="line">Primitive 2</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="240.1145" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="244.08325" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="31.750002" |
|||
y="244.08325" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[0]=0xffffffff (end)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
id="text4545"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4543" |
|||
x="31.750002" |
|||
y="295.67703" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Start of table</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4984);paint-order:normal" |
|||
d="m 5.5562491,242.76034 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
id="path4553" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="246.72908" |
|||
x="6.6145835" |
|||
height="5.2916694" |
|||
width="48.947918" |
|||
id="rect5546" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5550" |
|||
y="250.69783" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="250.69783" |
|||
x="31.750002" |
|||
id="tspan5548" |
|||
sodipodi:role="line">OT[1]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5576" |
|||
width="48.947918" |
|||
height="5.2916741" |
|||
x="6.6145835" |
|||
y="253.34367" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
id="text5580"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5578" |
|||
x="31.750002" |
|||
y="257.31244" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[2]</tspan></text> |
|||
<rect |
|||
y="259.95831" |
|||
x="6.6145835" |
|||
height="5.2916636" |
|||
width="48.947918" |
|||
id="rect5582" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5586" |
|||
y="263.92706" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="263.92706" |
|||
x="31.750002" |
|||
id="tspan5584" |
|||
sodipodi:role="line">OT[3]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5588" |
|||
width="48.947918" |
|||
height="5.2916536" |
|||
x="6.6145835" |
|||
y="266.57288" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
id="text5592"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5590" |
|||
x="31.750002" |
|||
y="270.54163" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[4]</tspan></text> |
|||
<rect |
|||
y="273.18747" |
|||
x="6.6145835" |
|||
height="5.2916741" |
|||
width="48.947918" |
|||
id="rect5594" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5598" |
|||
y="277.15622" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="277.15622" |
|||
x="31.750002" |
|||
id="tspan5596" |
|||
sodipodi:role="line">OT[5]</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5600" |
|||
width="48.947918" |
|||
height="5.2916636" |
|||
x="6.6145835" |
|||
y="279.80203" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
id="text5604"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5602" |
|||
x="31.750002" |
|||
y="283.77078" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">OT[6]</tspan></text> |
|||
<rect |
|||
y="286.41666" |
|||
x="6.6145835" |
|||
height="5.2916536" |
|||
width="48.947918" |
|||
id="rect5606" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
id="text5610" |
|||
y="290.38541" |
|||
x="31.750002" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="290.38541" |
|||
x="31.750002" |
|||
id="tspan5608" |
|||
sodipodi:role="line">OT[7]</tspan></text> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path13452" |
|||
d="m 56.620832,249.37492 2.381253,1e-5 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 h -3.439586" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker13622);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4571" |
|||
d="m 5.5562491,255.98951 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4575);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4587);paint-order:normal" |
|||
d="m 5.5562491,269.21868 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
id="path4583" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4589" |
|||
d="m 56.620832,275.83325 2.381253,10e-6 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 5.55625 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 h -3.439586" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4593);paint-order:normal" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path4595" |
|||
d="m 5.5562491,282.44784 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4599);paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4605);paint-order:normal" |
|||
d="m 56.620832,289.06242 2.381253,1e-5 c 0.264581,0 0.529164,0.26458 0.529164,0.52917 v 4.23333 c 0,0.26458 -0.264583,0.52916 -0.529164,0.52916 H 42.333332" |
|||
id="path4601" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<rect |
|||
y="263.39789" |
|||
x="68.791664" |
|||
height="5.2916584" |
|||
width="35.718754" |
|||
id="rect5707" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6049);paint-order:normal" |
|||
d="m 67.733333,272.39371 h -5.55625 c -1.852082,0 -0.529166,-3.17499 -2.645833,-3.17499 h -3.968751" |
|||
id="path6033" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker6581);paint-order:normal" |
|||
d="m 56.620833,262.60413 h 2.910416 c 2.116668,0 0.529165,-7.9375 2.645831,-7.9375 h 44.97917 c 0.79375,0 1.32292,0.52917 1.32292,1.32292 l 0,2.11666 c 0,0.79375 -0.52917,1.32292 -1.30202,1.32292 h -2.66673" |
|||
id="path6571" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccccc" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect7433" |
|||
width="35.718754" |
|||
height="5.2916689" |
|||
x="68.791664" |
|||
y="256.78329" /> |
|||
<rect |
|||
y="270.01245" |
|||
x="68.791664" |
|||
height="5.2916789" |
|||
width="35.718754" |
|||
id="rect7435" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker7561);paint-order:normal" |
|||
d="m 105.56875,266.04371 2.38126,1e-5 c 0.26458,0 0.52916,0.26458 0.52916,0.52917 v 5.55625 c 0,0.26458 -0.26458,0.52916 -0.52916,0.52916 h -3.43959" |
|||
id="path7557" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cccccc" /> |
|||
<path |
|||
sodipodi:nodetypes="cccccc" |
|||
inkscape:connector-curvature="0" |
|||
id="path7803" |
|||
d="m 67.733333,259.42913 h -2.38125 c -0.264583,0 -0.529166,0.26458 -0.529166,0.52917 v 5.55625 c 0,0.26458 0.264583,0.52916 0.529166,0.52916 h 3.439584" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker7807);paint-order:normal" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="85.989586" |
|||
y="260.48746" |
|||
id="text8261"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan8259" |
|||
x="85.989586" |
|||
y="260.48746" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Primitive 1</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:end;text-anchor:end;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="85.989586" |
|||
y="273.71664" |
|||
id="text8265"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan8263" |
|||
x="85.989586" |
|||
y="273.71664" |
|||
style="font-size:2.82222223px;text-align:center;text-anchor:middle;fill:#000000;stroke:none;stroke-width:0.26458332">Primitive 3</tspan></text> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,268 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:xlink="http://www.w3.org/1999/xlink" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="200" |
|||
height="300" |
|||
viewBox="0 0 52.916664 79.375004" |
|||
version="1.1" |
|||
id="svg4520" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="page-texcoord-relation.svg"> |
|||
<defs |
|||
id="defs4514"> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5610" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5608" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Lend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Lend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5111" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="marker5538" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5536" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.4,0,0,-0.4,-4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow2Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow2Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5117" |
|||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" |
|||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" |
|||
transform="scale(-0.6)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
<marker |
|||
inkscape:stockid="Arrow1Mend" |
|||
orient="auto" |
|||
refY="0" |
|||
refX="0" |
|||
id="Arrow1Mend" |
|||
style="overflow:visible" |
|||
inkscape:isstock="true"> |
|||
<path |
|||
id="path5099" |
|||
d="M 0,0 5,-5 -12.5,0 5,5 Z" |
|||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.00000003pt;stroke-opacity:1" |
|||
transform="matrix(-0.4,0,0,-0.4,-4,0)" |
|||
inkscape:connector-curvature="0" /> |
|||
</marker> |
|||
</defs> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1.3105469" |
|||
inkscape:cx="-1.1942734" |
|||
inkscape:cy="81.103977" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="false" |
|||
units="px" |
|||
inkscape:snap-global="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,500" |
|||
id="guide5076" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="132.29167,0" |
|||
orientation="-400,0" |
|||
id="guide5078" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="132.29167,105.83333" |
|||
orientation="0,-500" |
|||
id="guide5080" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,105.83333" |
|||
orientation="400,0" |
|||
id="guide5082" |
|||
inkscape:locked="false" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata4517"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title /> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-217.62498)"> |
|||
<image |
|||
y="225.03339" |
|||
x="7.4083333" |
|||
id="image6519" |
|||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAGACAMAAAB1HEyMAAAAM1BMVEUAAAD///9mosy2x4f58smA |
|||
y//m5ubMib/MxqX/qu7MzMz/VVXMQ0PMiYkAAADr/63/qqqvpluGAAAAAXRSTlMAQObYZgAAAAFi |
|||
S0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfkCwwBDwIUU2pJAAAFc0lEQVR4 |
|||
2u3d63LbNhAGULdJm6S39P2ftmJG2yIwSOFCha737J/IlnYBnMxwJMoz38tLVX/e6mWnjp47q3/l |
|||
9afMAAAgMcD24r9v1Wo6eu6s/pXXnzIDAAAA3xrqpr3fn90PAACAtwVQ1gzAaD8AAADeFsDe42f1 |
|||
AwAA4FqAaPqwU703RFb6typfH49HDz89AwCAxADxwq879WjQM/t7D7E0AwCAxABHG28Nuqr/EeD0 |
|||
DAAAEgOMbL415Ef3r/4HvJoBAACAwzcOAAAAeL8ARwf8eK8ZoJFN1DdOngVYrwMAAIDXzfHkx6pa |
|||
mzsLYKvPtzpaawWgPtO21u7VEwCApADxor9u9dO9oiF+3p4rNxePP91q9PBbTxwiDl+u04L41Fmt |
|||
g9fn+hcBAIDkALGR8iJUbqJsLi8icfCtvtyqXvzo4GVPCVCvU14Uo6dcK65j5cx4vnUhL88FAACA |
|||
/wC2plGAciPPBtiqPmB9Q6R+vjUDAAAAfQCPag9g5E1QC+Coyovu3k3R8vmeMwAAAOD7ewI9G9le |
|||
U9+QmP0wVB7gaO3WjZhHX4wcIXx3eAAAkgOUjfUmPt+rBfCsm6KtNVtrPLopWgOUcwEAALD/xUhr |
|||
A+WAR1+MfHhQRxez3sP3fjGyh3B49QQAICHAqz8aKDZTNz064Gh/64+e695Ha+09v7cHAAAAHNfP |
|||
t/qlqu13V/SP9J02BwCAxADRVDf3DlntBwAAwP8fIP4YKfrj51mA6O89eLkeAAAAxgGiuRzUe4B4 |
|||
7a+3iv54PAJQrh39IwBbTz0HAAAAfYtvNxDrDzPb70YvYuXFcOYCGPuIg4wAxJzyLF17AAAgOcBZ |
|||
NzS2i1D0xgVpde0ehHjN0hkAAEgMUL55qGv0w9Bo/+rap8wBAADAYfUsPtu/uvYpcwAASA4Q9dut |
|||
4sKxPR79UuKs/pfFml0fAAAAAAAAAAAAAICMAL/f6497xc9X9K8CzKwPAEBmAOnzAADkBRC+DgAA |
|||
AOHrAAAAEL4OAAAA6fMAAOQDiCbp8wAA5ASQPg8AQF4A6fMAAOQFEL4OAACA0WBlAAAAvA8A4esA |
|||
AABovUj6PAAAuQCkzwMAkBNA+DoAAACErwMAAED6PAAAOQHKD0TS5wEAyAcgfB0AAABlo/R5AADy |
|||
AUifBwAgL0Crrgxfr3tng5eX5gAAkBjgyvD1vd5RhKU5AAAkB2gNGN1EHba6ijcavg4AAIB1gDp0 |
|||
fRSgDFzvvQCWa82Grx/N6Q5uBAAgOUAMisD12Q9D5YwegHK9+oPMSOjr0RwAAADMfyAaAYjw9Xg8 |
|||
Eti6t/He8PWjOUvvpAAASAAgfB0AAADS5wEAyAsQdXXo6nRa7FlzAABIDlAe4kcvXsKtICzPAQAA |
|||
wGUA5R5mApi3nnoOAAAAxocMJ7ffazZAve5ZXb8+CwAAAI5L+jwAAHkBhK8DAABA+DoAAACErwMA |
|||
AED6PAAA+QCiSfo8AAA5AaTPAwCQF0D6PAAAeQGErwMAAGA0WBkAAADvA0D4OgAAAFovkj4PAEAu |
|||
AOnzAADkBBC+DgAAAOHrAAAAkD4PAEBOgPIDkfR5AADyAQhfBwAAQNkofR4AgHwA0ucBAMgL0Kor |
|||
w9db/ZcFsAMAkBDgyvD16J/tPWUOAADJAerm1dDV7d+R8PQzAMpgNQAAAMzNaQWwzwCUQeyja9Yh |
|||
6r17iDWX5gAAkBygDk+feRMyGt5+FJjcu4/ykCtzAADIDLD6RqQMXN96e8PXj26mnBW+PnRTBACA |
|||
hADC1wEAACB9HgCAvABRV4evrwa+Ls8BACA5QHywWAk/n108wtJHvlB5yhwAAABcBlDuYTZ8vZ4D |
|||
AACA/poNT683MRqe/mbS5wEAyAHwD75wEYolueMsAAAAAElFTkSuQmCC |
|||
" |
|||
style="image-rendering:optimizeSpeed" |
|||
preserveAspectRatio="none" |
|||
height="50.799862" |
|||
width="33.866665" /> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect5086" |
|||
width="8.4914379" |
|||
height="16.938023" |
|||
x="32.875015" |
|||
y="241.83257" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow2Mend);paint-order:normal" |
|||
d="M 7.4083321,225.03338 32.298196,241.38207" |
|||
id="path5088" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cc" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="M 7.4083331,292.0191 V 225.03338 H 44.693799" |
|||
id="path5084" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="ccc" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="15.797976" |
|||
y="284.42862" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="15.797976" |
|||
y="284.42862" |
|||
style="font-size:4.23333311px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">Texture Page</tspan><tspan |
|||
sodipodi:role="line" |
|||
x="15.797976" |
|||
y="289.72028" |
|||
style="font-size:4.23333311px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
id="tspan5903">Boundary</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="32.76712" |
|||
y="241.02052" |
|||
id="text4497-8"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495-5" |
|||
x="32.76712" |
|||
y="241.02052" |
|||
style="font-size:2.82222223px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">(48,32)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14.11111069px;line-height:1.25;font-family:HandelGotDLig;-inkscape-font-specification:HandelGotDLig;text-align:start;text-anchor:start;opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="37.349228" |
|||
y="269.88934" |
|||
id="text5522"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan5520" |
|||
x="37.349228" |
|||
y="283.18051" |
|||
style="stroke-width:0.26458332" /></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker5610);paint-order:normal" |
|||
d="M 14.873914,285.75994 H 8.9087441" |
|||
id="path5534" |
|||
inkscape:connector-curvature="0" |
|||
sodipodi:nodetypes="cc" /> |
|||
<text |
|||
id="text5866" |
|||
y="223.74693" |
|||
x="6.9488864" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.82222223px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="223.74693" |
|||
x="6.9488864" |
|||
id="tspan5864" |
|||
sodipodi:role="line">(0,0)</tspan></text> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,49 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
@ -0,0 +1,313 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="520" |
|||
height="290" |
|||
viewBox="0 0 137.58333 76.729169" |
|||
version="1.1" |
|||
id="svg8" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="vram-texture-coordinates.svg"> |
|||
<defs |
|||
id="defs2" /> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1.2022732" |
|||
inkscape:cx="202.46739" |
|||
inkscape:cy="213.9527" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="false" |
|||
units="px" |
|||
inkscape:snap-bbox="true" |
|||
inkscape:bbox-nodes="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:showpageshadow="false" |
|||
inkscape:snap-intersection-paths="true"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-256,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,67.733332" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,67.733332" |
|||
orientation="256,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title /> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-220.27081)"> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="135.46666" |
|||
height="67.73333" |
|||
x="1.0583369" |
|||
y="224.76869" |
|||
rx="2.0798286e-006" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="1.3450011" |
|||
y="223.73521" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="1.3450011" |
|||
y="223.73521" |
|||
style="font-size:2.82222223px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">(0,0)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="136.23978" |
|||
y="295.30496" |
|||
id="text4497-5"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495-0" |
|||
x="136.23978" |
|||
y="295.30496" |
|||
style="font-size:2.82222223px;text-align:end;text-anchor:end;fill:#000000;stroke:none;stroke-width:0.26458332">(1023,511)</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 69.092673,224.7687 v 67.73333" |
|||
id="path4497" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4499" |
|||
d="m 10.089578,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 119.66676,224.7687 v 67.73333" |
|||
id="path4501" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4503" |
|||
d="m 18.518593,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 111.23774,224.7687 v 67.73333" |
|||
id="path4505" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4507" |
|||
d="m 26.947605,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 102.80873,224.7687 v 67.73333" |
|||
id="path4509" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4511" |
|||
d="m 35.37662,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 94.379725,224.7687 v 67.73333" |
|||
id="path4513" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4515" |
|||
d="m 43.805637,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 85.950703,224.7687 v 67.73333" |
|||
id="path4517" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4519" |
|||
d="m 52.234652,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 77.521688,224.7687 v 67.73333" |
|||
id="path4521" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="M 1.0583692,257.12347 H 136.52503" |
|||
id="path4525" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4527" |
|||
d="m 60.663663,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<rect |
|||
style="opacity:1;fill:#ff0000;fill-opacity:0.50196078;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4529" |
|||
width="33.716049" |
|||
height="32.354763" |
|||
x="43.805637" |
|||
y="224.76871" /> |
|||
<text |
|||
id="text4533" |
|||
y="227.06142" |
|||
x="44.105091" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.11666656px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="227.06142" |
|||
x="44.105091" |
|||
id="tspan4531" |
|||
sodipodi:role="line">(0,0)</tspan></text> |
|||
<text |
|||
id="text4537" |
|||
y="256.33563" |
|||
x="77.18692" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.11666656px;text-align:end;text-anchor:end;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="256.33563" |
|||
x="77.18692" |
|||
id="tspan4535" |
|||
sodipodi:role="line">(255,255)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="60.543083" |
|||
y="241.99821" |
|||
id="text4541"><tspan |
|||
sodipodi:role="line" |
|||
x="60.543083" |
|||
y="241.99821" |
|||
style="font-size:2.82222223px;fill:#000000;stroke-width:0.26499999" |
|||
id="tspan4545">16-bit</tspan></text> |
|||
<rect |
|||
y="224.76871" |
|||
x="77.521683" |
|||
height="32.354763" |
|||
width="16.858042" |
|||
id="rect4549" |
|||
style="opacity:1;fill:#00ff00;fill-opacity:0.50196078;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="77.874794" |
|||
y="227.06142" |
|||
id="text4553"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4551" |
|||
x="77.874794" |
|||
y="227.06142" |
|||
style="font-size:2.11666656px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">(0,0)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="94.05928" |
|||
y="256.33563" |
|||
id="text4557"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4555" |
|||
x="94.05928" |
|||
y="256.33563" |
|||
style="font-size:2.11666656px;text-align:end;text-anchor:end;fill:#000000;stroke:none;stroke-width:0.26458332">(255,255)</tspan></text> |
|||
<text |
|||
id="text4565" |
|||
y="241.99821" |
|||
x="85.889381" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
id="tspan4563" |
|||
style="font-size:2.82222223px;fill:#000000;stroke-width:0.26499999" |
|||
y="241.99821" |
|||
x="85.889381" |
|||
sodipodi:role="line">8-bit</tspan></text> |
|||
<rect |
|||
style="opacity:1;fill:#0000ff;fill-opacity:0.50196078;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4577" |
|||
width="8.4290075" |
|||
height="32.354763" |
|||
x="94.379723" |
|||
y="224.76871" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="98.559776" |
|||
y="241.99821" |
|||
id="text4581"><tspan |
|||
sodipodi:role="line" |
|||
x="98.559776" |
|||
y="241.99821" |
|||
style="font-size:2.82222223px;fill:#000000;stroke-width:0.26499999" |
|||
id="tspan4579">4-bit</tspan></text> |
|||
<text |
|||
id="text7113" |
|||
y="227.06142" |
|||
x="94.60878" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.11666656px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="227.06142" |
|||
x="94.60878" |
|||
id="tspan7111" |
|||
sodipodi:role="line">(0,0)</tspan></text> |
|||
<text |
|||
id="text7117" |
|||
y="256.33563" |
|||
x="102.98763" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
xml:space="preserve"><tspan |
|||
style="font-size:2.11666656px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332" |
|||
y="256.33563" |
|||
x="102.98763" |
|||
id="tspan7115" |
|||
sodipodi:role="line">(255,255)</tspan></text> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4528" |
|||
d="m 128.09577,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,192 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|||
|
|||
<svg |
|||
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|||
xmlns:cc="http://creativecommons.org/ns#" |
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:svg="http://www.w3.org/2000/svg" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|||
width="520" |
|||
height="290" |
|||
viewBox="0 0 137.58333 76.729169" |
|||
version="1.1" |
|||
id="svg8" |
|||
inkscape:version="0.92.1 r15371" |
|||
sodipodi:docname="vram-texture-pages.svg"> |
|||
<defs |
|||
id="defs2" /> |
|||
<sodipodi:namedview |
|||
id="base" |
|||
pagecolor="#ffffff" |
|||
bordercolor="#666666" |
|||
borderopacity="1.0" |
|||
inkscape:pageopacity="0.0" |
|||
inkscape:pageshadow="2" |
|||
inkscape:zoom="1.2973752" |
|||
inkscape:cx="225.21048" |
|||
inkscape:cy="187.62673" |
|||
inkscape:document-units="mm" |
|||
inkscape:current-layer="layer1" |
|||
showgrid="false" |
|||
units="px" |
|||
inkscape:snap-bbox="true" |
|||
inkscape:bbox-nodes="true" |
|||
inkscape:window-width="1440" |
|||
inkscape:window-height="848" |
|||
inkscape:window-x="-8" |
|||
inkscape:window-y="-8" |
|||
inkscape:window-maximized="1" |
|||
inkscape:showpageshadow="false"> |
|||
<sodipodi:guide |
|||
position="0,0" |
|||
orientation="0,512" |
|||
id="guide4485" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,0" |
|||
orientation="-256,0" |
|||
id="guide4487" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="135.46666,67.733332" |
|||
orientation="0,-512" |
|||
id="guide4489" |
|||
inkscape:locked="false" /> |
|||
<sodipodi:guide |
|||
position="0,67.733332" |
|||
orientation="256,0" |
|||
id="guide4491" |
|||
inkscape:locked="false" /> |
|||
</sodipodi:namedview> |
|||
<metadata |
|||
id="metadata5"> |
|||
<rdf:RDF> |
|||
<cc:Work |
|||
rdf:about=""> |
|||
<dc:format>image/svg+xml</dc:format> |
|||
<dc:type |
|||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|||
<dc:title /> |
|||
</cc:Work> |
|||
</rdf:RDF> |
|||
</metadata> |
|||
<g |
|||
inkscape:label="Layer 1" |
|||
inkscape:groupmode="layer" |
|||
id="layer1" |
|||
transform="translate(0,-220.27081)"> |
|||
<rect |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
id="rect4493" |
|||
width="135.46666" |
|||
height="67.73333" |
|||
x="1.0583369" |
|||
y="224.76869" |
|||
rx="2.0798286e-006" /> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="1.3450011" |
|||
y="223.73521" |
|||
id="text4497"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495" |
|||
x="1.3450011" |
|||
y="223.73521" |
|||
style="font-size:2.82222223px;text-align:start;text-anchor:start;fill:#000000;stroke:none;stroke-width:0.26458332">(0,0)</tspan></text> |
|||
<text |
|||
xml:space="preserve" |
|||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-align:center;text-anchor:middle;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
x="136.23978" |
|||
y="295.30496" |
|||
id="text4497-5"><tspan |
|||
sodipodi:role="line" |
|||
id="tspan4495-0" |
|||
x="136.23978" |
|||
y="295.30496" |
|||
style="font-size:2.82222223px;text-align:end;text-anchor:end;fill:#000000;stroke:none;stroke-width:0.26458332">(1023,511)</tspan></text> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 68.550851,224.7687 v 67.73333" |
|||
id="path4497" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4499" |
|||
d="m 9.0721033,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 119.53264,224.7687 v 67.73333" |
|||
id="path4501" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4503" |
|||
d="m 17.569068,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 111.03567,224.7687 v 67.73333" |
|||
id="path4505" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4507" |
|||
d="m 26.066032,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 102.53871,224.7687 v 67.73333" |
|||
id="path4509" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4511" |
|||
d="m 34.562995,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 94.041737,224.7687 v 67.73333" |
|||
id="path4513" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4515" |
|||
d="m 43.059961,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 85.544775,224.7687 v 67.73333" |
|||
id="path4517" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4519" |
|||
d="m 51.556923,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="m 77.047814,224.7687 v 67.73333" |
|||
id="path4521" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" |
|||
d="M 1.0583692,257.12347 H 136.52503" |
|||
id="path4525" |
|||
inkscape:connector-curvature="0" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4527" |
|||
d="m 60.053889,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
<path |
|||
inkscape:connector-curvature="0" |
|||
id="path4506" |
|||
d="m 128.0296,224.7687 v 67.73333" |
|||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26146019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> |
|||
</g> |
|||
</svg> |
|||
@ -0,0 +1,672 @@ |
|||
<html><head><script src="Chapter%201.4%20Controllers_files/analytics.js" type="text/javascript"></script> |
|||
<script type="text/javascript">window.addEventListener('DOMContentLoaded',function(){var v=archive_analytics.values;v.service='wb';v.server_name='wwwb-app220.us.archive.org';v.server_ms=361;archive_analytics.send_pageview({});});</script> |
|||
<script type="text/javascript" src="Chapter%201.4%20Controllers_files/bundle-playback.js" charset="utf-8"></script> |
|||
<script type="text/javascript" src="Chapter%201.4%20Controllers_files/wombat.js" charset="utf-8"></script> |
|||
<script type="text/javascript"> |
|||
__wm.init("http://web.archive.org/web"); |
|||
__wm.wombat("http://lameguy64.net/tutorials/pstutorials/chapter1/4-controllers.html","20220827033533","http://web.archive.org/","web","/_static/", |
|||
"1661571333"); |
|||
</script> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.4%20Controllers_files/banner-styles.css"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.4%20Controllers_files/iconochive.css"> |
|||
<!-- End Wayback Rewrite JS Include --> |
|||
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.4%20Controllers_files/style.css"> |
|||
<title>Chapter 1.4: Controllers</title> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
|||
</head> |
|||
<body><!-- BEGIN WAYBACK TOOLBAR INSERT --> |
|||
<style type="text/css"> |
|||
body { |
|||
margin-top:0 !important; |
|||
padding-top:0 !important; |
|||
/*min-width:800px !important;*/ |
|||
} |
|||
</style> |
|||
<script>__wm.rw(0);</script> |
|||
<div id="wm-ipp-base" style="display: block; direction: ltr; height: 1px;" lang="en"> |
|||
</div><div id="wm-ipp-print">The Wayback Machine - |
|||
http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter1/4-controllers.html</div> |
|||
<script type="text/javascript">//<![CDATA[ |
|||
__wm.bt(675,27,25,2,"web","http://lameguy64.net/tutorials/pstutorials/chapter1/4-controllers.html","20220827033533",1996,"/_static/",["/_static/css/banner-styles.css?v=fantwOh2","/_static/css/iconochive.css?v=qtvMKcIJ"], false); |
|||
__wm.rw(1); |
|||
//]]></script> |
|||
<!-- END WAYBACK TOOLBAR INSERT --> |
|||
|
|||
<h1>Chapter 1.4: Controllers</h1> |
|||
|
|||
<p>One of the most important aspects when writing software for a game |
|||
console is taking input from a controller, as otherwise what's the point of |
|||
a game where the player can't take control of it? Unless its some demoscene |
|||
stuff you intend to write for the console.</p> |
|||
|
|||
<p>This chapter goes over how to initialize and handle controller input in |
|||
your PS1 program. This is something that hasn't really been explained very |
|||
well in many tutorials that I've seen in my personal experience, so I'll try |
|||
my best to explain how controller input is handled on the PS1 in great |
|||
detail.</p> |
|||
|
|||
<p><b>Compatible with PSn00bSDK:</b> Yes</p> |
|||
|
|||
<h2>Tutorial Index</h2> |
|||
<ul> |
|||
<li><a href="#getinput">Methods to Obtain Controller Input</a></li> |
|||
<li><a href="#initpad">Initializing the Pad Subsystem</a></li> |
|||
<li><a href="#parsepad">Parsing Controller Data</a></li> |
|||
<li><a href="#implementation">Implementation</a></li> |
|||
<li><a href="#conclusion">Conclusion</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="getinput">Methods to Obtain Controller Input</h2> |
|||
|
|||
<p>There are a number of ways to obtain input from the controller on the |
|||
PS1; direct hardware access (complicated), through BIOS |
|||
<b>InitPAD()/StartPAD()</b> (simpler, but has some limitations), though |
|||
<b>PadInit()/PadRead()</b> (even simpler, but only works with digital |
|||
pads), and through various controller related libraries such as |
|||
libtap, libgun and libpad provided in the PsyQ/Programmers' Tool SDK.</p> |
|||
|
|||
<p>The most common method people tend to use is <b>PadInit()</b> and |
|||
<b>PadRead()</b>, and whilst it is the most simplest to use it is not |
|||
exactly the most ideal method for a proper game project. For one it only |
|||
works with digital pads and Dual-shock pads with analog turned off. Secondly, |
|||
there's no way to determine if a pad is disconnected or not and rumble |
|||
features on Dual-shock pads cannot be accessed with it. It is, however, |
|||
ideal for prototype test programs.</p> |
|||
|
|||
<p>Another method which is a little more ideal is to use <b>InitPAD()</b> |
|||
and <b>StartPAD()</b> which are provided by the BIOS ROM of the console. This |
|||
method is not only capable of determining if a controller is attached or not |
|||
but it also works with a wider variety of controllers including multi-taps. |
|||
The only controllers that it doesn't really support properly are both the |
|||
Namco and Konami lightguns as they need to be polled in a specific way for |
|||
it to work, which is not supported by these functions. Lightguns are beyond |
|||
the scope for this chapter anyway. It still cannot access rumble features |
|||
of Dual-analog and Dual-shock controllers however.</p> |
|||
|
|||
<p>For compatibility with PSn00bSDK, only the BIOS <b>InitPAD()</b> and |
|||
<b>StartPAD()</b> functions will be covered in this chapter. In the future, |
|||
I will look into making a follow-up that uses libpad or a similar equivalent |
|||
library for PSn00bSDK that would also cover accessing rumble features of |
|||
Dual-analog and Dual-shock pads.</p> |
|||
|
|||
|
|||
<h2 id="initpad">Initializing the Pad Subsystem</h2> |
|||
|
|||
<p>The first step is to define an array of two 34 byte elements. This array |
|||
will be used as a buffer for storing incoming controller data which requires |
|||
at least about 34 bytes per controller port. It may sound a bit excessive for |
|||
storing input data, but this is necessary in case a multitap is connected to |
|||
one of the ports, as a multitap will return up to 34 bytes from all four |
|||
controllers connected to the tap.</p> |
|||
|
|||
<pre>u_char padbuff[2][34]; |
|||
</pre> |
|||
|
|||
<p>Next is to call <b>InitPAD()</b> to define the pad array to the BIOS |
|||
controller subsystem. libpad still uses the same buffer format that |
|||
<b>InitPAD()</b> would return data to, so upgrading from the BIOS pad |
|||
routines to libpad should be pretty trivial.</p> |
|||
|
|||
<pre>InitPAD( padbuff[0], 34, padbuff[1], 34 ); |
|||
</pre> |
|||
|
|||
<p>Before you start controller polling, it may be a good idea to set the |
|||
first two elements of both arrays with 0xff, so that your program won't |
|||
process faulty input when the array is parsed with zero filled data. You'll |
|||
figure out why later in this chapter.</p> |
|||
|
|||
<pre>padbuff[0][0] = padbuff[0][1] = 0xff; |
|||
padbuff[1][0] = padbuff[1][1] = 0xff; |
|||
</pre> |
|||
|
|||
<p>Then start controller polling with <b>StartPAD()</b>.</p> |
|||
|
|||
<pre>StartPAD(); |
|||
</pre> |
|||
|
|||
<p>After calling <b>StartPAD()</b> and you have a tty console in your |
|||
development setup (or the message window in no$psx), you may see the |
|||
message <i>"VSync: Timeout"</i> pop-up when your program reaches a |
|||
<b>VSync</b> call. This happens because <b>StartPAD()</b> annoyingly |
|||
re-enables automatic VSync interrupt acknowledge in the PS1's kernel, |
|||
preventing the <b>VSync()</b> function from detecting a VSync interrupt |
|||
from occuring. Fortunately, it has a timeout, of which it will disable |
|||
the automatic VSync acknowledge so it can detect VSync interrupts again. |
|||
This can happen on both Programmer's Tool and PSn00bSDK.</p> |
|||
|
|||
<p>In PSn00bSDK, you can avoid this message by calling |
|||
<b>ChangeClearPAD(1)</b> after <b>StartPAD()</b>, but this function is only |
|||
really exposed in PSn00bSDK.</p> |
|||
|
|||
<p>It is generally unnecessary to stop controller polling using |
|||
<b>StopPAD()</b>, plus it may cause Dual-shock controllers to reset their |
|||
controller mode back to digital mode. If you're using BIOS memory card |
|||
functions later down the line, stopping pads will also stop memory cards |
|||
as well. Using <b>StopPAD()</b> is only really required when transferring |
|||
execution to a child PS-EXE or another PS-EXE altogether.</p> |
|||
|
|||
|
|||
<h2 id="parsepad">Parsing Controller Data</h2> |
|||
|
|||
<p>After calling <b>StartPAD()</b>, the <h>padbuff</h> array will be filled |
|||
with controller data in every frame. For NTSC systems this is 60 times a |
|||
second and 50 for PAL systems. Therefore, the controller ports are polled |
|||
automatically, so the only thing to do next is to parse the input data |
|||
stored in the arrays.</p> |
|||
|
|||
<p>Because the PS1's BIOS controller handler depends on VSync interrupts to |
|||
poll the controller ports, you will not be able to receive further inputs |
|||
when interrupts are disabled, but this isn't really something to worry about |
|||
yet at this point in this tutorial series.</p> |
|||
|
|||
<p>Now, onto the pad buffer data. The first byte stored in the <h>padbuff</h> |
|||
array denotes the status of the port. A value of zero indicates that a |
|||
device (ie. controller) is connected to the port and the rest of the array |
|||
contains valid controller data.</p> |
|||
<pre>if( padbuff[0][0] == 0 ) |
|||
{ |
|||
// controller on port 1 connected |
|||
} |
|||
</pre> |
|||
<p>The following byte is the controller ID, denoting both the controller |
|||
type and the number of bytes the controller has sent to the console. The |
|||
controller type is stored in the upper 4 bits of the ID byte while the data |
|||
byte is at the lower 4 bits.</p> |
|||
|
|||
<pre>padtype = padbuff[0][1]>>4; // get the controller type |
|||
padlen = padbuff[0][1]&0xF; // get the data length (normally not needed) |
|||
</pre> |
|||
|
|||
<p>The following table lists controller type values that are relevant to this |
|||
chapter. Lightgun IDs are omitted as you won't be able to poll them properly |
|||
anyway.</p> |
|||
|
|||
<center> |
|||
<table class="bordered-table"> |
|||
<tbody><tr> |
|||
<th>Controller</th><th>Type Value</th> |
|||
</tr> |
|||
<tr><td>Mouse</td><td>0x1</td></tr> |
|||
<tr><td>Namco NegCon</td><td>0x2</td></tr> |
|||
<tr><td>Digital pad or Dual-shock in digital mode (no light)</td><td>0x4</td></tr> |
|||
<tr><td>Analog Stick or Dual-analog in green mode</td><td>0x5</td></tr> |
|||
<tr><td>Dual-shock in analog mode or Dual-analog in red mode</td><td>0x7</td></tr> |
|||
<tr><td>Namco JogCon</td><td>0xE</td></tr> |
|||
</tbody></table> |
|||
</center> |
|||
|
|||
<p>The two bytes following the ID byte are usually the controller's digital |
|||
button states as a 16-bit integer, with each bit representing the state |
|||
of one button. Oddly, the bit states are inverted, where a bit value of 1 |
|||
means released and a value of 0 means pressed.</p> |
|||
|
|||
<p>The following table lists which bit of the 16-bit word corresponds to each |
|||
button of a standard digital pad or Dual-shock controller. Both controllers |
|||
share the same bit positions.</p> |
|||
|
|||
<center> |
|||
<table class="bordered-table"> |
|||
<tbody><tr><th>Bit</th><th>Button</th></tr> |
|||
<tr><td>0</td><td>Select</td></tr> |
|||
<tr><td>1</td><td>L3 (Dual-shock only)</td></tr> |
|||
<tr><td>2</td><td>R3 (Dual-shock only)</td></tr> |
|||
<tr><td>3</td><td>Start</td></tr> |
|||
<tr><td>4</td><td>Up</td></tr> |
|||
<tr><td>5</td><td>Right</td></tr> |
|||
<tr><td>6</td><td>Down</td></tr> |
|||
<tr><td>7</td><td>Left</td></tr> |
|||
<tr><td>8</td><td>L2</td></tr> |
|||
<tr><td>9</td><td>R2</td></tr> |
|||
<tr><td>10</td><td>L1</td></tr> |
|||
<tr><td>11</td><td>R1</td></tr> |
|||
<tr><td>12</td><td>Triangle</td></tr> |
|||
<tr><td>13</td><td>Circle</td></tr> |
|||
<tr><td>14</td><td>Cross</td></tr> |
|||
<tr><td>15</td><td>Square</td></tr> |
|||
</tbody></table> |
|||
</center> |
|||
|
|||
<p>It may be a good idea to define a list of constants for each button so |
|||
you can specify which bit to test with more coherent names. In PSn00bSDK, |
|||
these are already defined in <h>psxpad.h.</h></p> |
|||
|
|||
<pre>#define PAD_SELECT 1 |
|||
#define PAD_L3 2 |
|||
#define PAD_R3 4 |
|||
#define PAD_START 8 |
|||
#define PAD_UP 16 |
|||
#define PAD_RIGHT 32 |
|||
#define PAD_DOWN 64 |
|||
#define PAD_LEFT 128 |
|||
#define PAD_L2 256 |
|||
#define PAD_R2 512 |
|||
#define PAD_L1 1024 |
|||
#define PAD_R1 2048 |
|||
#define PAD_TRIANGLE 4096 |
|||
#define PAD_CIRCLE 8192 |
|||
#define PAD_CROSS 16384 |
|||
#define PAD_SQUARE 32768 |
|||
</pre> |
|||
|
|||
<p>To test if a button is pressed, simply mask the 16-bit integer against the |
|||
bit value of the button you want to test using an AND (&) operator. Because |
|||
the pressed state of a button is zero, you'll have to follow it up with a |
|||
NOT (!) operator as well.</p> |
|||
|
|||
<pre>u_short button; |
|||
|
|||
... |
|||
|
|||
button = *((u_short*)(padbuff[0]+2)); |
|||
|
|||
// is cross pressed? |
|||
if( !( button & PAD_CROSS ) ) |
|||
{ |
|||
// do something when cross is pressed |
|||
} |
|||
</pre> |
|||
|
|||
<p>If you only need to support regular controllers (digital, analog stick, |
|||
Dual-analog, Dual-shock), a simplle struct like this should suffice for |
|||
all the four controller types and with analog input on controllers with |
|||
such features. In PSn00bSDK, the following struct is already defined in |
|||
<h>psxpad.h</h>.</p> |
|||
|
|||
<pre>typedef struct _PADTYPE |
|||
{ |
|||
unsigned char stat; |
|||
unsigned char len:4; |
|||
unsigned char type:4; |
|||
unsigned short btn; |
|||
unsigned char rs_x,rs_y; |
|||
unsigned char ls_x,ls_y; |
|||
} PADTYPE; |
|||
</pre> |
|||
|
|||
<p>If the connected controller doesn't feature any analog inputs, the |
|||
elements following <h>btn</h> relating to analog sticks can be ignored.</p> |
|||
|
|||
<p>When parsing analog stick inputs, remember that the coordinates when the |
|||
stick is at its center position is not always 128, due to deadzones and |
|||
other factors that affect the potentiometers. Its recommended to implement |
|||
a simple threshold to make sure your code does not register false inputs |
|||
(at least to the player) when the stick is placed at its center position.</p> |
|||
|
|||
<p>For more information about controller input data, you may want to check |
|||
the <a href="http://web.archive.org/web/20220827033533/http://problemkaputt.de/psx-spx.htm#controllersstandarddigitalanalogcontrollers"> |
|||
Controllers Chapter</a> in nocash's PSX specs document.</p> |
|||
|
|||
|
|||
<h2 id="implementation">Implementation</h2> |
|||
|
|||
<p>As an exercise for this chapter, we're going to make the textured sprite |
|||
from the last chapter move using the controller. Begin by adding the button |
|||
definitions, structs and <h>padbuff</h> array described in this chapter near |
|||
the beginning of the source file, but must be placed <b>after</b> the |
|||
<h>#include</h> directives. When using PSn00bSDK, you can simply include |
|||
<h>psxpad.h</h> instead, which already has those defined.</p> |
|||
|
|||
<p>Next, place the <b>InitPAD()</b> and <b>StartPAD()</b> calls at the end |
|||
of your <b>init()</b> function, so pads get initialized alongside the |
|||
graphics. If you're using PSn00bSDK, you can add <b>ChangeClearPAD(1)</b> |
|||
after <b>StartPAD()</b> to avoid the <h>VSync: Timeout</h> message from |
|||
cropping up in your tty terminal.</p> |
|||
|
|||
<p>Next, define two variables named <i>pos_x</i> and <i>pos_y</i> of type |
|||
<b>int</b> at the start of the <b>main()</b> function, preferably before |
|||
the line that defines the <b>TILE</b> variable. These will be for storing |
|||
the X,Y coordinates for the textured sprite. Following that, define a |
|||
variable <i>pad</i> of type <b>PADTYPE</b>, this will be used for reading |
|||
controller inputs more easily.</p> |
|||
|
|||
<p>Before the while loop, set both <i>pos_x</i> and <i>pos_y</i> to 48 to |
|||
make sure they don't contain a random undefined value. Within the loop, add |
|||
the following code that parses the controller and performs actions according |
|||
to controller inputs.</p> |
|||
|
|||
<pre>pad = (PADTYPE*)padbuff[0]; |
|||
|
|||
// Only parse inputs when a controller is connected |
|||
if( pad->stat == 0 ) |
|||
{ |
|||
// Only parse when a digital pad, |
|||
// dual-analog and dual-shock is connected |
|||
if( ( pad->type == 0x4 ) || |
|||
( pad->type == 0x5 ) || |
|||
( pad->type == 0x7 ) ) |
|||
{ |
|||
if( !(pad->btn&PAD;_UP) ) // test UP |
|||
{ |
|||
pos_y--; |
|||
} |
|||
else if( !(pad->btn&PAD;_UP) ) // test DOWN |
|||
{ |
|||
pos_y++; |
|||
} |
|||
if( !(pad->btn&PAD;_LEFT) ) // test LEFT |
|||
{ |
|||
pos_x--; |
|||
} |
|||
else if( !(pad->btn&PAD;_RIGHT) ) // test RIGHT |
|||
{ |
|||
pos_x++; |
|||
} |
|||
} |
|||
} |
|||
</pre> |
|||
|
|||
<p>Now, go to the bit of code that sorts the textured sprite, and modify |
|||
the <b>setXY0</b> macro call to use X,Y coordinates from <i>pos_x</i> and |
|||
<i>pos_y</i>.</p> |
|||
|
|||
<pre>setXY0(sprt, pos_x, pos_y); |
|||
</pre> |
|||
|
|||
<p>If you followed the instructions properly, the source code should look |
|||
like this:</p> |
|||
|
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <libetc.h> // Includes some functions that controls the display |
|||
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <libgpu.h> // GPU library header |
|||
#include <libapi.h> // API header, has InitPAD() and StartPAD() defs |
|||
|
|||
#define OTLEN 8 // Ordering table length (recommended to set as a define |
|||
// so it can be changed easily) |
|||
|
|||
DISPENV disp[2]; // Display/drawing buffer parameters |
|||
DRAWENV draw[2]; |
|||
int db = 0; |
|||
|
|||
// PSn00bSDK requires having all u_long types replaced with |
|||
// u_int, as u_long in modern GCC that PSn00bSDK uses defines it as a 64-bit integer. |
|||
|
|||
u_long ot[2][OTLEN]; // Ordering table length |
|||
char pribuff[2][32768]; // Primitive buffer |
|||
char *nextpri; // Next primitive pointer |
|||
|
|||
int tim_mode; // TIM image parameters |
|||
RECT tim_prect,tim_crect; |
|||
int tim_uoffs,tim_voffs; |
|||
|
|||
// Pad stuff (omit when using PSn00bSDK) |
|||
#define PAD_SELECT 1 |
|||
#define PAD_L3 2 |
|||
#define PAD_R3 4 |
|||
#define PAD_START 8 |
|||
#define PAD_UP 16 |
|||
#define PAD_RIGHT 32 |
|||
#define PAD_DOWN 64 |
|||
#define PAD_LEFT 128 |
|||
#define PAD_L2 256 |
|||
#define PAD_R2 512 |
|||
#define PAD_L1 1024 |
|||
#define PAD_R1 2048 |
|||
#define PAD_TRIANGLE 4096 |
|||
#define PAD_CIRCLE 8192 |
|||
#define PAD_CROSS 16384 |
|||
#define PAD_SQUARE 32768 |
|||
|
|||
typedef struct _PADTYPE |
|||
{ |
|||
unsigned char stat; |
|||
unsigned char len:4; |
|||
unsigned char type:4; |
|||
unsigned short btn; |
|||
unsigned char rs_x,rs_y; |
|||
unsigned char ls_x,ls_y; |
|||
} PADTYPE; |
|||
|
|||
// pad buffer arrays |
|||
u_char padbuff[2][34]; |
|||
|
|||
void display() { |
|||
|
|||
DrawSync(0); // Wait for any graphics processing to finish |
|||
|
|||
VSync(0); // Wait for vertical retrace |
|||
|
|||
PutDispEnv(&disp;[db]); // Apply the DISPENV/DRAWENVs |
|||
PutDrawEnv(&draw;[db]); |
|||
|
|||
SetDispMask(1); // Enable the display |
|||
|
|||
DrawOTag(ot[db]+OTLEN-1); // Draw the ordering table |
|||
|
|||
db = !db; // Swap buffers on every pass (alternates between 1 and 0) |
|||
nextpri = pribuff[db]; // Reset next primitive pointer |
|||
|
|||
} |
|||
|
|||
// Texture upload function |
|||
void LoadTexture(u_long *tim, TIM_IMAGE *tparam) { |
|||
|
|||
// Read TIM parameters (PsyQ) |
|||
OpenTIM(tim); |
|||
ReadTIM(tparam); |
|||
|
|||
// Read TIM parameters (PSn00bSDK) |
|||
//GetTimInfo(tim, tparam); |
|||
|
|||
// Upload pixel data to framebuffer |
|||
LoadImage(tparam->prect, (u_long*)tparam->paddr); |
|||
DrawSync(0); |
|||
|
|||
// Upload CLUT to framebuffer if present |
|||
if( tparam->mode & 0x8 ) { |
|||
|
|||
LoadImage(tparam->crect, (u_long*)tparam->caddr); |
|||
DrawSync(0); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
void loadstuff(void) { |
|||
|
|||
TIM_IMAGE my_image; // TIM image parameters |
|||
|
|||
extern u_long tim_my_image[]; |
|||
|
|||
// Load the texture |
|||
LoadTexture(tim_my_image, &my;_image); |
|||
|
|||
// Copy the TIM coordinates |
|||
tim_prect = *my_image.prect; |
|||
tim_crect = *my_image.crect; |
|||
tim_mode = my_image.mode; |
|||
|
|||
// Calculate U,V offset for TIMs that are not page aligned |
|||
tim_uoffs = (tim_prect.x%64)<<(2-(tim_mode&0x3)); |
|||
tim_voffs = (tim_prect.y&0xff); |
|||
|
|||
} |
|||
|
|||
// To make main look tidy, init stuff has to be moved here |
|||
void init(void) { |
|||
|
|||
// Reset graphics |
|||
ResetGraph(0); |
|||
|
|||
// First buffer |
|||
SetDefDispEnv(&disp;[0], 0, 0, 320, 240); |
|||
SetDefDrawEnv(&draw;[0], 0, 240, 320, 240); |
|||
// Second buffer |
|||
SetDefDispEnv(&disp;[1], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw;[1], 0, 0, 320, 240); |
|||
|
|||
draw[0].isbg = 1; // Enable clear |
|||
setRGB0(&draw;[0], 63, 0, 127); // Set clear color (dark purple) |
|||
draw[1].isbg = 1; |
|||
setRGB0(&draw;[1], 63, 0, 127); |
|||
|
|||
nextpri = pribuff[0]; // Set initial primitive pointer address |
|||
|
|||
// load textures and possibly other stuff |
|||
loadstuff(); |
|||
|
|||
// set tpage of lone texture as initial tpage |
|||
draw[0].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
draw[1].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
|
|||
// apply initial drawing environment |
|||
PutDrawEnv(&draw;[!db]); |
|||
|
|||
// Initialize the pads |
|||
InitPAD( padbuff[0], 34, padbuff[1], 34 ); |
|||
|
|||
// Begin polling |
|||
StartPAD(); |
|||
|
|||
// To avoid VSync Timeout error, may not be defined in PsyQ |
|||
ChangeClearPAD( 1 ); |
|||
|
|||
} |
|||
|
|||
int main() { |
|||
|
|||
int pos_x,pos_y; |
|||
PADTYPE *pad; |
|||
|
|||
TILE *tile; // Pointer for TILE |
|||
SPRT *sprt; // Pointer for SPRT |
|||
|
|||
// Init stuff |
|||
init(); |
|||
|
|||
pos_x = pos_y = 48; |
|||
|
|||
while(1) { |
|||
|
|||
// Parse controller input |
|||
pad = (PADTYPE*)padbuff[0]; |
|||
|
|||
// Only parse inputs when a controller is connected |
|||
if( pad->stat == 0 ) |
|||
{ |
|||
// Only parse when a digital pad, |
|||
// dual-analog and dual-shock is connected |
|||
if( ( pad->type == 0x4 ) || |
|||
( pad->type == 0x5 ) || |
|||
( pad->type == 0x7 ) ) |
|||
{ |
|||
if( !(pad->btn&PAD;_UP) ) // test UP |
|||
{ |
|||
pos_y--; |
|||
} |
|||
else if( !(pad->btn&PAD;_DOWN) ) // test DOWN |
|||
{ |
|||
pos_y++; |
|||
} |
|||
if( !(pad->btn&PAD;_LEFT) ) // test LEFT |
|||
{ |
|||
pos_x--; |
|||
} |
|||
else if( !(pad->btn&PAD;_RIGHT) ) // test RIGHT |
|||
{ |
|||
pos_x++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
ClearOTagR(ot[db], OTLEN); // Clear ordering table |
|||
|
|||
// Sort textured sprite |
|||
|
|||
sprt = (SPRT*)nextpri; |
|||
|
|||
setSprt(sprt); // Initialize the primitive (very important) |
|||
setXY0(sprt, pos_x, pos_y); // Position the sprite at (48,48) |
|||
setWH(sprt, 64, 64); // Set size to 64x64 pixels |
|||
setUV0(sprt, // Set UV coordinates |
|||
tim_uoffs, |
|||
tim_voffs); |
|||
setClut(sprt, // Set CLUT coordinates to sprite |
|||
tim_crect.x, |
|||
tim_crect.y); |
|||
setRGB0(sprt, // Set primitive color |
|||
128, 128, 128); |
|||
addPrim(ot[db], sprt); // Sort primitive to OT |
|||
|
|||
nextpri += sizeof(SPRT); // Advance next primitive address |
|||
|
|||
|
|||
// Sort untextured tile primitive from the last tutorial |
|||
|
|||
tile = (TILE*)nextpri; // Cast next primitive |
|||
|
|||
setTile(tile); // Initialize the primitive (very important) |
|||
setXY0(tile, 32, 32); // Set primitive (x,y) position |
|||
setWH(tile, 64, 64); // Set primitive size |
|||
setRGB0(tile, 255, 255, 0); // Set color yellow |
|||
addPrim(ot[db], tile); // Add primitive to the ordering table |
|||
|
|||
nextpri += sizeof(TILE); // Advance the next primitive pointer |
|||
|
|||
|
|||
// Update the display |
|||
display(); |
|||
|
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
|
|||
<p>Compile, execute and you should get a textured sprite that you can move |
|||
around with the directional pad of the controller.</p> |
|||
|
|||
<center> |
|||
<img src="Chapter%201.4%20Controllers_files/spritemove.png"> |
|||
</center> |
|||
|
|||
|
|||
<h2 id="conclusion">Conclusion</h2> |
|||
|
|||
<p>Hopefully, this chapter should teach you about getting controller input |
|||
more than using <b>PadInit()</b> and <b>PadStart()</b>. The only downside |
|||
with this method is that you can't control the vibration motors of either |
|||
Dual-analog or Dual-shock controllers, or enabling analog mode on Dual-shock |
|||
controllers in software. Hopefully, this will be covered in a future chapter |
|||
of this tutorial series.</p> |
|||
|
|||
<p>In the next chapter, we'll be looking into handling analog inputs and a |
|||
glimpse of fixed-point integer math for performing fractional calculations |
|||
without using floats.</p> |
|||
|
|||
<hr> |
|||
<table width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter1/3-textures.html">Previous</a></td> |
|||
<td width="20%" align="center"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter1/5-fixedpoint.html">Next</a></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
|
|||
</body></html> |
|||
<!-- |
|||
FILE ARCHIVED ON 03:35:33 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:39:08 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
--> |
|||
<!-- |
|||
playback timings (ms): |
|||
captures_list: 132.108 |
|||
exclusion.robots: 0.302 |
|||
exclusion.robots.policy: 0.289 |
|||
RedisCDXSource: 72.486 |
|||
esindex: 0.008 |
|||
LoadShardBlock: 40.136 (3) |
|||
PetaboxLoader3.datanode: 53.118 (4) |
|||
CDXLines.iter: 16.216 (3) |
|||
load_resource: 221.534 |
|||
PetaboxLoader3.resolve: 179.474 |
|||
--> |
|||
@ -0,0 +1,474 @@ |
|||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3.0
|
|||
/* eslint-disable no-var, semi, prefer-arrow-callback, prefer-template */ |
|||
|
|||
/** |
|||
* Collection of methods for sending analytics events to Archive.org's analytics server. |
|||
* |
|||
* These events are used for internal stats and sent (in anonymized form) to Google Analytics. |
|||
* |
|||
* @see analytics.md |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
window.archive_analytics = (function defineArchiveAnalytics() { |
|||
// keep orignal Date object so as not to be affected by wayback's
|
|||
// hijacking global Date object
|
|||
var Date = window.Date; |
|||
var ARCHIVE_ANALYTICS_VERSION = 2; |
|||
var DEFAULT_SERVICE = 'ao_2'; |
|||
var NO_SAMPLING_SERVICE = 'ao_no_sampling'; // sends every event instead of a percentage
|
|||
|
|||
var startTime = new Date(); |
|||
|
|||
/** |
|||
* @return {Boolean} |
|||
*/ |
|||
function isPerformanceTimingApiSupported() { |
|||
return 'performance' in window && 'timing' in window.performance; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the browser starting to parse the DOM and |
|||
* the current time. |
|||
* |
|||
* Uses the Performance API or a fallback value if it's not available. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number} |
|||
*/ |
|||
function getLoadTime() { |
|||
var start; |
|||
|
|||
if (isPerformanceTimingApiSupported()) |
|||
start = window.performance.timing.domLoading; |
|||
else |
|||
start = startTime.getTime(); |
|||
|
|||
return new Date().getTime() - start; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the user navigating to the page and |
|||
* the current time. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number|null} null if the browser doesn't support the Performance API |
|||
*/ |
|||
function getNavToDoneTime() { |
|||
if (!isPerformanceTimingApiSupported()) |
|||
return null; |
|||
|
|||
return new Date().getTime() - window.performance.timing.navigationStart; |
|||
} |
|||
|
|||
/** |
|||
* Performs an arithmetic calculation on a string with a number and unit, while maintaining |
|||
* the unit. |
|||
* |
|||
* @param {String} original value to modify, with a unit |
|||
* @param {Function} doOperation accepts one Number parameter, returns a Number |
|||
* @returns {String} |
|||
*/ |
|||
function computeWithUnit(original, doOperation) { |
|||
var number = parseFloat(original, 10); |
|||
var unit = original.replace(/(\d*\.\d+)|\d+/, ''); |
|||
|
|||
return doOperation(number) + unit; |
|||
} |
|||
|
|||
/** |
|||
* Computes the default font size of the browser. |
|||
* |
|||
* @returns {String|null} computed font-size with units (typically pixels), null if it cannot be computed |
|||
*/ |
|||
function getDefaultFontSize() { |
|||
var fontSizeStr; |
|||
|
|||
if (!('getComputedStyle' in window)) |
|||
return null; |
|||
|
|||
var style = window.getComputedStyle(document.documentElement); |
|||
if (!style) |
|||
return null; |
|||
|
|||
fontSizeStr = style.fontSize; |
|||
|
|||
// Don't modify the value if tracking book reader.
|
|||
if (document.querySelector('#BookReader')) |
|||
return fontSizeStr; |
|||
|
|||
return computeWithUnit(fontSizeStr, function reverseBootstrapFontSize(number) { |
|||
// Undo the 62.5% size applied in the Bootstrap CSS.
|
|||
return number * 1.6; |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Get the URL parameters for a given Location |
|||
* @param {Location} |
|||
* @return {Object} The URL parameters |
|||
*/ |
|||
function getParams(location) { |
|||
if (!location) location = window.location; |
|||
var vars; |
|||
var i; |
|||
var pair; |
|||
var params = {}; |
|||
var query = location.search; |
|||
if (!query) return params; |
|||
vars = query.substring(1).split('&'); |
|||
for (i = 0; i < vars.length; i++) { |
|||
pair = vars[i].split('='); |
|||
params[pair[0]] = decodeURIComponent(pair[1]); |
|||
} |
|||
return params; |
|||
} |
|||
|
|||
function getMetaProp(name) { |
|||
var metaTag = document.querySelector('meta[property=' + name + ']'); |
|||
return metaTag ? metaTag.getAttribute('content') || null : null; |
|||
} |
|||
|
|||
var ArchiveAnalytics = { |
|||
/** |
|||
* @type {String|null} |
|||
*/ |
|||
service: getMetaProp('service'), |
|||
mediaType: getMetaProp('mediatype'), |
|||
primaryCollection: getMetaProp('primary_collection'), |
|||
|
|||
/** |
|||
* Key-value pairs to send in pageviews (you can read this after a pageview to see what was |
|||
* sent). |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
values: {}, |
|||
|
|||
/** |
|||
* Sends an analytics ping, preferably using navigator.sendBeacon() |
|||
* @param {Object} values |
|||
* @param {Function} [onload_callback] (deprecated) callback to invoke once ping to analytics server is done |
|||
* @param {Boolean} [augment_for_ao_site] (deprecated) if true, add some archive.org site-specific values |
|||
*/ |
|||
send_ping: function send_ping(values, onload_callback, augment_for_ao_site) { |
|||
if (typeof window.navigator !== 'undefined' && typeof window.navigator.sendBeacon !== 'undefined') |
|||
this.send_ping_via_beacon(values); |
|||
else |
|||
this.send_ping_via_image(values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Beacon API |
|||
* NOTE: Assumes window.navigator.sendBeacon exists |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_beacon: function send_ping_via_beacon(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
window.navigator.sendBeacon(url); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Image object |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_image: function send_ping_via_image(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
var loadtime_img = new Image(1, 1); |
|||
loadtime_img.src = url; |
|||
loadtime_img.alt = ''; |
|||
}, |
|||
|
|||
/** |
|||
* Construct complete tracking URL containing payload |
|||
* @param {Object} params Tracking parameters to pass |
|||
* @return {String} URL to use for tracking call |
|||
*/ |
|||
generate_tracking_url: function generate_tracking_url(params) { |
|||
var baseUrl = '//analytics.archive.org/0.gif'; |
|||
var keys; |
|||
var outputParams = params; |
|||
var outputParamsArray = []; |
|||
|
|||
outputParams.service = outputParams.service || this.service || DEFAULT_SERVICE; |
|||
|
|||
// Build array of querystring parameters
|
|||
keys = Object.keys(outputParams); |
|||
keys.forEach(function keyIteration(key) { |
|||
outputParamsArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(outputParams[key])); |
|||
}); |
|||
outputParamsArray.push('version=' + ARCHIVE_ANALYTICS_VERSION); |
|||
outputParamsArray.push('count=' + (keys.length + 2)); // Include `version` and `count` in count
|
|||
|
|||
return baseUrl + '?' + outputParamsArray.join('&'); |
|||
}, |
|||
|
|||
/** |
|||
* @param {int} page Page number |
|||
*/ |
|||
send_scroll_fetch_event: function send_scroll_fetch_event(page) { |
|||
var additionalValues = { ev: page }; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
send_scroll_fetch_base_event: function send_scroll_fetch_base_event() { |
|||
var additionalValues = {}; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch_base', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} [options] |
|||
* @param {String} [options.mediaType] |
|||
* @param {String} [options.mediaLanguage] |
|||
* @param {String} [options.page] The path portion of the page URL |
|||
*/ |
|||
send_pageview: function send_pageview(options) { |
|||
var settings = options || {}; |
|||
|
|||
var defaultFontSize; |
|||
var loadTime = getLoadTime(); |
|||
var mediaType = settings.mediaType; |
|||
var primaryCollection = settings.primaryCollection; |
|||
var page = settings.page; |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
|
|||
/** |
|||
* @return {String} |
|||
*/ |
|||
function get_locale() { |
|||
if (navigator) { |
|||
if (navigator.language) |
|||
return navigator.language; |
|||
|
|||
else if (navigator.browserLanguage) |
|||
return navigator.browserLanguage; |
|||
|
|||
else if (navigator.systemLanguage) |
|||
return navigator.systemLanguage; |
|||
|
|||
else if (navigator.userLanguage) |
|||
return navigator.userLanguage; |
|||
} |
|||
return ''; |
|||
} |
|||
|
|||
defaultFontSize = getDefaultFontSize(); |
|||
|
|||
// Set field values
|
|||
this.values.kind = 'pageview'; |
|||
this.values.timediff = (new Date().getTimezoneOffset()/60)*(-1); // *timezone* diff from UTC
|
|||
this.values.locale = get_locale(); |
|||
this.values.referrer = (document.referrer == '' ? '-' : document.referrer); |
|||
|
|||
if (loadTime) |
|||
this.values.loadtime = loadTime; |
|||
|
|||
if (navToDoneTime) |
|||
this.values.nav_to_done_ms = navToDoneTime; |
|||
|
|||
if (settings.trackingId) { |
|||
this.values.ga_tid = settings.trackingId; |
|||
} |
|||
|
|||
/* START CUSTOM DIMENSIONS */ |
|||
if (defaultFontSize) |
|||
this.values.ga_cd1 = defaultFontSize; |
|||
|
|||
if ('devicePixelRatio' in window) |
|||
this.values.ga_cd2 = window.devicePixelRatio; |
|||
|
|||
if (mediaType) |
|||
this.values.ga_cd3 = mediaType; |
|||
|
|||
if (settings.mediaLanguage) { |
|||
this.values.ga_cd4 = settings.mediaLanguage; |
|||
} |
|||
|
|||
if (primaryCollection) { |
|||
this.values.ga_cd5 = primaryCollection; |
|||
} |
|||
/* END CUSTOM DIMENSIONS */ |
|||
|
|||
if (page) |
|||
this.values.page = page; |
|||
|
|||
this.send_ping(this.values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a tracking "Event". |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event: function send_event( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
if (!label) label = window.location.pathname; |
|||
if (!additionalEventParams) additionalEventParams = {}; |
|||
if (additionalEventParams.mediaLanguage) { |
|||
additionalEventParams.ga_cd4 = additionalEventParams.mediaLanguage; |
|||
delete additionalEventParams.mediaLanguage; |
|||
} |
|||
var eventParams = Object.assign( |
|||
{ |
|||
kind: 'event', |
|||
ec: category, |
|||
ea: action, |
|||
el: label, |
|||
cache_bust: Math.random(), |
|||
}, |
|||
additionalEventParams |
|||
); |
|||
this.send_ping(eventParams); |
|||
}, |
|||
|
|||
/** |
|||
* Sends every event instead of a small percentage. |
|||
* |
|||
* Use this sparingly as it can generate a lot of events. |
|||
* |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event_no_sampling: function send_event_no_sampling( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
var extraParams = additionalEventParams || {}; |
|||
extraParams.service = NO_SAMPLING_SERVICE; |
|||
this.send_event(category, action, label, extraParams); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} options see this.send_pageview options |
|||
*/ |
|||
send_pageview_on_load: function send_pageview_on_load(options) { |
|||
var self = this; |
|||
window.addEventListener('load', function send_pageview_with_options() { |
|||
self.send_pageview(options); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* Handles tracking events passed in URL. |
|||
* Assumes category and action values are separated by a "|" character. |
|||
* NOTE: Uses the unsampled analytics property. Watch out for future high click links! |
|||
* @param {Location} |
|||
*/ |
|||
process_url_events: function process_url_events(location) { |
|||
var eventValues; |
|||
var actionValue; |
|||
var eventValue = getParams(location).iax; |
|||
if (!eventValue) return; |
|||
eventValues = eventValue.split('|'); |
|||
actionValue = eventValues.length >= 1 ? eventValues[1] : ''; |
|||
this.send_event_no_sampling( |
|||
eventValues[0], |
|||
actionValue, |
|||
window.location.pathname |
|||
); |
|||
}, |
|||
|
|||
/** |
|||
* Attaches handlers for event tracking. |
|||
* |
|||
* To enable click tracking for a link, add a `data-event-click-tracking` |
|||
* attribute containing the Google Analytics Event Category and Action, separated |
|||
* by a vertical pipe (|). |
|||
* e.g. `<a href="foobar" data-event-click-tracking="TopNav|FooBar">` |
|||
* |
|||
* To enable form submit tracking, add a `data-event-form-tracking` attribute |
|||
* to the `form` tag. |
|||
* e.g. `<form data-event-form-tracking="TopNav|SearchForm" method="GET">` |
|||
* |
|||
* Additional tracking options can be added via a `data-event-tracking-options` |
|||
* parameter. This parameter, if included, should be a JSON string of the parameters. |
|||
* Valid parameters are: |
|||
* - service {string}: Corresponds to the Google Analytics property data values flow into |
|||
*/ |
|||
set_up_event_tracking: function set_up_event_tracking() { |
|||
var self = this; |
|||
var clickTrackingAttributeName = 'event-click-tracking'; |
|||
var formTrackingAttributeName = 'event-form-tracking'; |
|||
var trackingOptionsAttributeName = 'event-tracking-options'; |
|||
|
|||
function handleAction(event, attributeName) { |
|||
var selector = '[data-' + attributeName + ']'; |
|||
var eventTarget = event.target; |
|||
if (!eventTarget) return; |
|||
var target = eventTarget.closest(selector); |
|||
if (!target) return; |
|||
var categoryAction; |
|||
var categoryActionParts; |
|||
var options; |
|||
categoryAction = target.dataset[toCamelCase(attributeName)]; |
|||
if (!categoryAction) return; |
|||
categoryActionParts = categoryAction.split('|'); |
|||
options = target.dataset[toCamelCase(trackingOptionsAttributeName)]; |
|||
options = options ? JSON.parse(options) : {}; |
|||
self.send_event( |
|||
categoryActionParts[0], |
|||
categoryActionParts[1], |
|||
categoryActionParts[2] || window.location.pathname, |
|||
options.service ? { service: options.service } : {} |
|||
); |
|||
} |
|||
|
|||
function toCamelCase(str) { |
|||
return str.replace(/\W+(.)/g, function (match, chr) { |
|||
return chr.toUpperCase(); |
|||
}); |
|||
}; |
|||
|
|||
document.addEventListener('click', function(e) { |
|||
handleAction(e, clickTrackingAttributeName); |
|||
}); |
|||
|
|||
document.addEventListener('submit', function(e) { |
|||
handleAction(e, formTrackingAttributeName); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* @returns {Object[]} |
|||
*/ |
|||
get_data_packets: function get_data_packets() { |
|||
return [this.values]; |
|||
}, |
|||
|
|||
/** |
|||
* Creates a tracking image for tracking JS compatibility. |
|||
* |
|||
* @param {string} type The type value for track_js_case in query params for 0.gif |
|||
*/ |
|||
create_tracking_image: function create_tracking_image(type) { |
|||
this.send_ping_via_image({ |
|||
cache_bust: Math.random(), |
|||
kind: 'track_js', |
|||
track_js_case: type, |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
return ArchiveAnalytics; |
|||
}()); |
|||
// @license-end
|
|||
@ -0,0 +1,500 @@ |
|||
@import 'record.css'; /* for SPN1 */ |
|||
|
|||
#wm-ipp-base { |
|||
height:65px;/* initial height just in case js code fails */ |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
background:none transparent; |
|||
} |
|||
#wm-ipp { |
|||
z-index: 2147483647; |
|||
} |
|||
#wm-ipp, #wm-ipp * { |
|||
font-family:Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size:12px; |
|||
line-height:1.2; |
|||
letter-spacing:0; |
|||
width:auto; |
|||
height:auto; |
|||
max-width:none; |
|||
max-height:none; |
|||
min-width:0 !important; |
|||
min-height:0; |
|||
outline:none; |
|||
float:none; |
|||
text-align:left; |
|||
border:none; |
|||
color: #000; |
|||
text-indent: 0; |
|||
position: initial; |
|||
background: none; |
|||
} |
|||
#wm-ipp div, #wm-ipp canvas { |
|||
display: block; |
|||
} |
|||
#wm-ipp div, #wm-ipp tr, #wm-ipp td, #wm-ipp a, #wm-ipp form { |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
border-radius:0; |
|||
background-color:transparent; |
|||
background-image:none; |
|||
/*z-index:2147483640;*/ |
|||
height:auto; |
|||
} |
|||
#wm-ipp table { |
|||
border:none; |
|||
border-collapse:collapse; |
|||
margin:0; |
|||
padding:0; |
|||
width:auto; |
|||
font-size:inherit; |
|||
} |
|||
#wm-ipp form input { |
|||
padding:1px !important; |
|||
height:auto; |
|||
display:inline; |
|||
margin:0; |
|||
color: #000; |
|||
background: none #fff; |
|||
border: 1px solid #666; |
|||
} |
|||
#wm-ipp form input[type=submit] { |
|||
padding:0 8px !important; |
|||
margin:1px 0 1px 5px !important; |
|||
width:auto !important; |
|||
border: 1px solid #000 !important; |
|||
background: #fff !important; |
|||
color: #000 !important; |
|||
} |
|||
#wm-ipp a { |
|||
display: inline; |
|||
} |
|||
#wm-ipp a:hover{ |
|||
text-decoration:underline; |
|||
} |
|||
#wm-ipp a.wm-btn:hover { |
|||
text-decoration:none; |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp a.wm-btn:hover span { |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp #wm-ipp-inside { |
|||
margin: 0 6px; |
|||
border:5px solid #000; |
|||
border-top:none; |
|||
background-color:rgba(255,255,255,0.9); |
|||
-moz-box-shadow:1px 1px 4px #333; |
|||
-webkit-box-shadow:1px 1px 4px #333; |
|||
box-shadow:1px 1px 4px #333; |
|||
border-radius:0 0 8px 8px; |
|||
} |
|||
/* selectors are intentionally verbose to ensure priority */ |
|||
#wm-ipp #wm-logo { |
|||
padding:0 10px; |
|||
vertical-align:middle; |
|||
min-width:100px; |
|||
flex: 0 0 100px; |
|||
} |
|||
#wm-ipp .c { |
|||
padding-left: 4px; |
|||
} |
|||
#wm-ipp .c .u { |
|||
margin-top: 4px !important; |
|||
} |
|||
#wm-ipp .n { |
|||
padding:0 0 0 5px !important; |
|||
vertical-align: bottom; |
|||
} |
|||
#wm-ipp .n a { |
|||
text-decoration:none; |
|||
color:#33f; |
|||
font-weight:bold; |
|||
} |
|||
#wm-ipp .n .b { |
|||
padding:0 6px 0 0 !important; |
|||
text-align:right !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n .y .b { |
|||
padding:0 6px 2px 0 !important; |
|||
} |
|||
#wm-ipp .n .c { |
|||
background:#000; |
|||
color:#ff0; |
|||
font-weight:bold; |
|||
padding:0 !important; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp.hi .n td.c { |
|||
color:#ec008c; |
|||
} |
|||
#wm-ipp .n td.f { |
|||
padding:0 0 0 6px !important; |
|||
text-align:left !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n tr.m td { |
|||
text-transform:uppercase; |
|||
white-space:nowrap; |
|||
padding:2px 0; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 0 0 !important; |
|||
vertical-align:bottom; |
|||
} |
|||
#wm-ipp #wm-nav-captures { |
|||
white-space: nowrap; |
|||
} |
|||
#wm-ipp .c .s a.t { |
|||
color:#33f; |
|||
font-weight:bold; |
|||
line-height: 1.8; |
|||
} |
|||
#wm-ipp .c .s div.r { |
|||
color: #666; |
|||
font-size:9px; |
|||
white-space:nowrap; |
|||
} |
|||
#wm-ipp .c .k { |
|||
padding-bottom:1px; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayMonthEl { |
|||
padding: 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayYearEl { |
|||
padding: 0 0 2px 0 !important; |
|||
} |
|||
|
|||
div#wm-ipp-sparkline { |
|||
position:relative;/* for positioning markers */ |
|||
white-space:nowrap; |
|||
background-color:#fff; |
|||
cursor:pointer; |
|||
line-height:0.9; |
|||
} |
|||
#sparklineImgId, #wm-sparkline-canvas { |
|||
position:relative; |
|||
z-index:9012; |
|||
max-width:none; |
|||
} |
|||
#wm-ipp-sparkline div.yt { |
|||
position:absolute; |
|||
z-index:9010 !important; |
|||
background-color:#ff0 !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp-sparkline div.mt { |
|||
position:absolute; |
|||
z-index:9013 !important; |
|||
background-color:#ec008c !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp .r { |
|||
margin-left: 4px; |
|||
} |
|||
#wm-ipp .r a { |
|||
color:#33f; |
|||
border:none; |
|||
position:relative; |
|||
background-color:transparent; |
|||
background-repeat:no-repeat !important; |
|||
background-position:100% 100% !important; |
|||
text-decoration: none; |
|||
} |
|||
#wm-ipp #wm-capinfo { |
|||
/* prevents notice div background from sticking into round corners of |
|||
#wm-ipp-inside */ |
|||
border-radius: 0 0 4px 4px; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo { |
|||
display:block; |
|||
float:left; |
|||
margin-right:3px; |
|||
width:90px; |
|||
min-height:90px; |
|||
max-height: 290px; |
|||
border-radius:45px; |
|||
overflow:hidden; |
|||
background-position:50%; |
|||
background-size:auto 90px; |
|||
box-shadow: 0 0 2px 2px rgba(208,208,208,128) inset; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo span { |
|||
display:inline-block; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo img { |
|||
height:90px; |
|||
position:relative; |
|||
left:-50%; |
|||
} |
|||
#wm-ipp #wm-capinfo .wm-title { |
|||
font-size:130%; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector { |
|||
display:inline-block; |
|||
color: #aaa; |
|||
text-decoration:none !important; |
|||
padding: 2px 8px; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector.selected { |
|||
background-color:#666; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector:hover { |
|||
color: #fff; |
|||
} |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-collected-by, |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-timestamps { |
|||
display: none; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content { |
|||
background-color:#ff0; |
|||
padding:5px; |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content * { |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-expand { |
|||
right: 1px; |
|||
bottom: -1px; |
|||
color: #ffffff; |
|||
background-color: #666 !important; |
|||
padding:0 5px 0 3px !important; |
|||
border-radius: 3px 3px 0 0 !important; |
|||
} |
|||
#wm-ipp #wm-expand span { |
|||
color: #ffffff; |
|||
} |
|||
#wm-ipp #wm-expand #wm-expand-icon { |
|||
display: inline-block; |
|||
transition: transform 0.5s; |
|||
transform-origin: 50% 45%; |
|||
} |
|||
#wm-ipp #wm-expand.wm-open #wm-expand-icon { |
|||
transform: rotate(180deg); |
|||
} |
|||
#wm-ipp #wmtb { |
|||
text-align:right; |
|||
} |
|||
#wm-ipp #wmtb #wmtbURL { |
|||
width: calc(100% - 45px); |
|||
} |
|||
#wm-ipp #wm-graph-anchor { |
|||
border-right:1px solid #ccc; |
|||
} |
|||
/* time coherence */ |
|||
html.wb-highlight { |
|||
box-shadow: inset 0 0 0 3px #a50e3a !important; |
|||
} |
|||
.wb-highlight { |
|||
outline: 3px solid #a50e3a !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:none !important; |
|||
} |
|||
@media print { |
|||
#wm-ipp-base { |
|||
display:none !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:block !important; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
} |
|||
@media (max-width:414px) { |
|||
#wm-ipp .xxs { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (min-width:1055px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:block !important; |
|||
} |
|||
} |
|||
@media (max-width:1054px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (max-width:1163px) { |
|||
#wm-logo { |
|||
display:none !important; |
|||
} |
|||
} |
|||
|
|||
#wm-btns { |
|||
white-space: nowrap; |
|||
margin-top: -2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-open { |
|||
margin-right: 7px; |
|||
top: -6px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in { |
|||
box-sizing: content-box; |
|||
display: none; |
|||
margin-right: 7px; |
|||
top: -8px; |
|||
|
|||
/* |
|||
round border around sign in button |
|||
*/ |
|||
border: 2px #000 solid; |
|||
border-radius: 14px; |
|||
padding-right: 2px; |
|||
padding-bottom: 2px; |
|||
width: 11px; |
|||
height: 11px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in>.iconochive-person { |
|||
font-size: 12.5px; |
|||
} |
|||
|
|||
#wm-save-snapshot-open > .iconochive-web { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-ipp #wm-share { |
|||
display: flex; |
|||
align-items: flex-end; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
#wm-share > #wm-screenshot { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-screenshot > .iconochive-image { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-share > #wm-video { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-video > .iconochive-movies { |
|||
color: #000; |
|||
display: inline-block; |
|||
font-size: 150%; |
|||
margin-bottom: 2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-in-progress { |
|||
display: none; |
|||
font-size:160%; |
|||
opacity: 0.5; |
|||
position: relative; |
|||
margin-right: 7px; |
|||
top: -5px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-success { |
|||
display: none; |
|||
color: green; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-fail { |
|||
display: none; |
|||
color: red; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
.wm-icon-screen-shot { |
|||
background: url("../images/web-screenshot.svg") no-repeat !important; |
|||
background-size: contain !important; |
|||
width: 22px !important; |
|||
height: 19px !important; |
|||
|
|||
display: inline-block; |
|||
} |
|||
#donato { |
|||
/* transition effect is disable so as to simplify height adjustment */ |
|||
/*transition: height 0.5s;*/ |
|||
height: 0; |
|||
margin: 0; |
|||
padding: 0; |
|||
border-bottom: 1px solid #999 !important; |
|||
} |
|||
body.wm-modal { |
|||
height: auto !important; |
|||
overflow: hidden !important; |
|||
} |
|||
#donato #donato-base { |
|||
width: 100%; |
|||
height: 100%; |
|||
/*bottom: 0;*/ |
|||
margin: 0; |
|||
padding: 0; |
|||
position: absolute; |
|||
z-index: 2147483639; |
|||
} |
|||
body.wm-modal #donato #donato-base { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 2147483640; |
|||
} |
|||
|
|||
.wb-autocomplete-suggestions { |
|||
font-family: Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size: 12px; |
|||
text-align: left; |
|||
cursor: default; |
|||
border: 1px solid #ccc; |
|||
border-top: 0; |
|||
background: #fff; |
|||
box-shadow: -1px 1px 3px rgba(0,0,0,.1); |
|||
position: absolute; |
|||
display: none; |
|||
z-index: 2147483647; |
|||
max-height: 254px; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
box-sizing: border-box; |
|||
} |
|||
.wb-autocomplete-suggestion { |
|||
position: relative; |
|||
padding: 0 .6em; |
|||
line-height: 23px; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
font-size: 1.02em; |
|||
color: #333; |
|||
} |
|||
.wb-autocomplete-suggestion b { |
|||
font-weight: bold; |
|||
} |
|||
.wb-autocomplete-suggestion.selected { |
|||
background: #f0f0f0; |
|||
} |
|||
3
Docs/Chapter 1.4 Controllers_files/bundle-playback.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,116 @@ |
|||
@font-face{font-family:'Iconochive-Regular';src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?-ccsheb');src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?#iefix-ccsheb') format('embedded-opentype'),url('https://archive.org/includes/fonts/Iconochive-Regular.woff?-ccsheb') format('woff'),url('https://archive.org/includes/fonts/Iconochive-Regular.ttf?-ccsheb') format('truetype'),url('https://archive.org/includes/fonts/Iconochive-Regular.svg?-ccsheb#Iconochive-Regular') format('svg');font-weight:normal;font-style:normal} |
|||
[class^="iconochive-"],[class*=" iconochive-"]{font-family:'Iconochive-Regular'!important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} |
|||
.iconochive-Uplevel:before{content:"\21b5"} |
|||
.iconochive-exit:before{content:"\1f6a3"} |
|||
.iconochive-beta:before{content:"\3b2"} |
|||
.iconochive-logo:before{content:"\1f3db"} |
|||
.iconochive-audio:before{content:"\1f568"} |
|||
.iconochive-movies:before{content:"\1f39e"} |
|||
.iconochive-software:before{content:"\1f4be"} |
|||
.iconochive-texts:before{content:"\1f56e"} |
|||
.iconochive-etree:before{content:"\1f3a4"} |
|||
.iconochive-image:before{content:"\1f5bc"} |
|||
.iconochive-web:before{content:"\1f5d4"} |
|||
.iconochive-collection:before{content:"\2211"} |
|||
.iconochive-folder:before{content:"\1f4c2"} |
|||
.iconochive-data:before{content:"\1f5c3"} |
|||
.iconochive-tv:before{content:"\1f4fa"} |
|||
.iconochive-article:before{content:"\1f5cf"} |
|||
.iconochive-question:before{content:"\2370"} |
|||
.iconochive-question-dark:before{content:"\3f"} |
|||
.iconochive-info:before{content:"\69"} |
|||
.iconochive-info-small:before{content:"\24d8"} |
|||
.iconochive-comment:before{content:"\1f5e9"} |
|||
.iconochive-comments:before{content:"\1f5ea"} |
|||
.iconochive-person:before{content:"\1f464"} |
|||
.iconochive-people:before{content:"\1f465"} |
|||
.iconochive-eye:before{content:"\1f441"} |
|||
.iconochive-rss:before{content:"\221e"} |
|||
.iconochive-time:before{content:"\1f551"} |
|||
.iconochive-quote:before{content:"\275d"} |
|||
.iconochive-disc:before{content:"\1f4bf"} |
|||
.iconochive-tv-commercial:before{content:"\1f4b0"} |
|||
.iconochive-search:before{content:"\1f50d"} |
|||
.iconochive-search-star:before{content:"\273d"} |
|||
.iconochive-tiles:before{content:"\229e"} |
|||
.iconochive-list:before{content:"\21f6"} |
|||
.iconochive-list-bulleted:before{content:"\2317"} |
|||
.iconochive-latest:before{content:"\2208"} |
|||
.iconochive-left:before{content:"\2c2"} |
|||
.iconochive-right:before{content:"\2c3"} |
|||
.iconochive-left-solid:before{content:"\25c2"} |
|||
.iconochive-right-solid:before{content:"\25b8"} |
|||
.iconochive-up-solid:before{content:"\25b4"} |
|||
.iconochive-down-solid:before{content:"\25be"} |
|||
.iconochive-dot:before{content:"\23e4"} |
|||
.iconochive-dots:before{content:"\25a6"} |
|||
.iconochive-columns:before{content:"\25af"} |
|||
.iconochive-sort:before{content:"\21d5"} |
|||
.iconochive-atoz:before{content:"\1f524"} |
|||
.iconochive-ztoa:before{content:"\1f525"} |
|||
.iconochive-upload:before{content:"\1f4e4"} |
|||
.iconochive-download:before{content:"\1f4e5"} |
|||
.iconochive-favorite:before{content:"\2605"} |
|||
.iconochive-heart:before{content:"\2665"} |
|||
.iconochive-play:before{content:"\25b6"} |
|||
.iconochive-play-framed:before{content:"\1f3ac"} |
|||
.iconochive-fullscreen:before{content:"\26f6"} |
|||
.iconochive-mute:before{content:"\1f507"} |
|||
.iconochive-unmute:before{content:"\1f50a"} |
|||
.iconochive-share:before{content:"\1f381"} |
|||
.iconochive-edit:before{content:"\270e"} |
|||
.iconochive-reedit:before{content:"\2710"} |
|||
.iconochive-gear:before{content:"\2699"} |
|||
.iconochive-remove-circle:before{content:"\274e"} |
|||
.iconochive-plus-circle:before{content:"\1f5d6"} |
|||
.iconochive-minus-circle:before{content:"\1f5d5"} |
|||
.iconochive-x:before{content:"\1f5d9"} |
|||
.iconochive-fork:before{content:"\22d4"} |
|||
.iconochive-trash:before{content:"\1f5d1"} |
|||
.iconochive-warning:before{content:"\26a0"} |
|||
.iconochive-flash:before{content:"\1f5f2"} |
|||
.iconochive-world:before{content:"\1f5fa"} |
|||
.iconochive-lock:before{content:"\1f512"} |
|||
.iconochive-unlock:before{content:"\1f513"} |
|||
.iconochive-twitter:before{content:"\1f426"} |
|||
.iconochive-facebook:before{content:"\66"} |
|||
.iconochive-googleplus:before{content:"\67"} |
|||
.iconochive-reddit:before{content:"\1f47d"} |
|||
.iconochive-tumblr:before{content:"\54"} |
|||
.iconochive-pinterest:before{content:"\1d4df"} |
|||
.iconochive-popcorn:before{content:"\1f4a5"} |
|||
.iconochive-email:before{content:"\1f4e7"} |
|||
.iconochive-embed:before{content:"\1f517"} |
|||
.iconochive-gamepad:before{content:"\1f579"} |
|||
.iconochive-Zoom_In:before{content:"\2b"} |
|||
.iconochive-Zoom_Out:before{content:"\2d"} |
|||
.iconochive-RSS:before{content:"\1f4e8"} |
|||
.iconochive-Light_Bulb:before{content:"\1f4a1"} |
|||
.iconochive-Add:before{content:"\2295"} |
|||
.iconochive-Tab_Activity:before{content:"\2318"} |
|||
.iconochive-Forward:before{content:"\23e9"} |
|||
.iconochive-Backward:before{content:"\23ea"} |
|||
.iconochive-No_Audio:before{content:"\1f508"} |
|||
.iconochive-Pause:before{content:"\23f8"} |
|||
.iconochive-No_Favorite:before{content:"\2606"} |
|||
.iconochive-Unike:before{content:"\2661"} |
|||
.iconochive-Song:before{content:"\266b"} |
|||
.iconochive-No_Flag:before{content:"\2690"} |
|||
.iconochive-Flag:before{content:"\2691"} |
|||
.iconochive-Done:before{content:"\2713"} |
|||
.iconochive-Check:before{content:"\2714"} |
|||
.iconochive-Refresh:before{content:"\27f3"} |
|||
.iconochive-Headphones:before{content:"\1f3a7"} |
|||
.iconochive-Chart:before{content:"\1f4c8"} |
|||
.iconochive-Bookmark:before{content:"\1f4d1"} |
|||
.iconochive-Documents:before{content:"\1f4da"} |
|||
.iconochive-Newspaper:before{content:"\1f4f0"} |
|||
.iconochive-Podcast:before{content:"\1f4f6"} |
|||
.iconochive-Radio:before{content:"\1f4fb"} |
|||
.iconochive-Cassette:before{content:"\1f4fc"} |
|||
.iconochive-Shuffle:before{content:"\1f500"} |
|||
.iconochive-Loop:before{content:"\1f501"} |
|||
.iconochive-Low_Audio:before{content:"\1f509"} |
|||
.iconochive-First:before{content:"\1f396"} |
|||
.iconochive-Invisible:before{content:"\1f576"} |
|||
.iconochive-Computer:before{content:"\1f5b3"} |
|||
@ -0,0 +1,70 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
/* |
|||
FILE ARCHIVED ON 03:35:25 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:39:09 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
*/ |
|||
/* |
|||
playback timings (ms): |
|||
captures_list: 107.165 |
|||
exclusion.robots: 0.073 |
|||
exclusion.robots.policy: 0.067 |
|||
cdx.remote: 0.064 |
|||
esindex: 0.009 |
|||
LoadShardBlock: 52.713 (3) |
|||
PetaboxLoader3.datanode: 140.466 (4) |
|||
CDXLines.iter: 14.771 (3) |
|||
load_resource: 139.896 |
|||
PetaboxLoader3.resolve: 47.824 |
|||
*/ |
|||
21
Docs/Chapter 1.4 Controllers_files/wombat.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,826 @@ |
|||
<html><head> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.5%20Fixed%20point%20Math_files/style.css"> |
|||
<title>Chapter 1.5: Fixed point Math</title> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
|||
</head> |
|||
<body> |
|||
|
|||
<h1>Chapter 1.5: Fixed Point Math</h1> |
|||
|
|||
<p>If you've been trying to write some games on a modern system (ie. your |
|||
PC), you probably already know about using floats to implement momentum and |
|||
jumping physics in a 2D platformer, or have something move towards a direction |
|||
specified in degrees rather than X,Y velocity values to have said object |
|||
move at an angle, like a ship in an Asteroids style game or a car in a |
|||
top-down racer... On the PlayStation, these principles still apply. But |
|||
there's a problem; the PlayStation does not have a hardware floating point |
|||
unit.</p> |
|||
|
|||
<p>Whilst you can still use floats on the PlayStation as the compiler will |
|||
resort to software emulation to perform such operations, which you might |
|||
be able to get away with, it's not exactly the most ideal method as software |
|||
emulation of floats is quite slow, and will become an issue if used for |
|||
collision detection or processing movement of a hundred projectile |
|||
entities... The alternative that's better suited for a system without a |
|||
floating point unit is to use a integer based fractional number system |
|||
commonly known as fixed point math.</p> |
|||
|
|||
<p>As the name suggests, fixed point math is a trick for storing fractional |
|||
numbers with fixed points, in this case an integer scale of 4096 will have |
|||
a range between zero to 4095 representing a fractional value, with 4096 |
|||
representing a integer value of 1. Fixed point math is used heavily in games |
|||
made for systems that lacked a floating point unit (5th generation and older |
|||
consoles), or where integer math is considerably faster than floating point |
|||
math and not all systems feature a floating point unit |
|||
(ie. IBM compatible PCs).</p> |
|||
|
|||
<p>This chapter covers the general idea and basics of performing fixed point |
|||
integer arithmetic. This is a highly essential chapter when getting into |
|||
PlayStation homebrew development, as learning it will increase the range of |
|||
games you can write for the console immensely. If you've already learned some |
|||
binary encoding of numeric values this chapter might be a bit easier to |
|||
understand.</p> |
|||
|
|||
<p><b>Compatible with PSn00bSDK:</b> Yes</p> |
|||
|
|||
<h2>Tutorial Index</h2> |
|||
<ul> |
|||
<li><a href="#principles">Principle of Fixed Point Math</a></li> |
|||
<li><a href="#basics">Fixed Point Arithmetic Basics</a></li> |
|||
<li><a href="#tankcontrols">Implementing Tank Controls with Fixed Point</a></li> |
|||
<li><a href="#asteroids">Asteroids Style Physics with Fixed Point</a></li> |
|||
<li><a href="#spriterot">Bonus: Fixed Point Sprite Rotation</a></li> |
|||
<li><a href="#limitations">Limitations of Fixed Point Math</a></li> |
|||
<li><a href="#conclusion">Conclusion and Further Reading</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="principles">Principle of Fixed Point Math</h2> |
|||
|
|||
<p>The basic principle of fixed point integer math is instead of representing |
|||
a real number of 1.25 as a floating point number, you instead represent |
|||
the number as an integer value from a scale value, in this case 4096 which is |
|||
defined as <b>ONE</b> in the GTE library headers. So a real value of 1.25 |
|||
will look like 5120 when converted to fixed point math with a scale of 4096. |
|||
Converting a floating point number to a fixed point number is achieved by |
|||
simply multiplying the real number against the scale value and rounding off |
|||
the fractions, turning the result into a plain integer value. The following |
|||
table shows some sample floating point values represented in fixed point.</p> |
|||
|
|||
<center> |
|||
<table class="bordered-table"> |
|||
<tbody><tr> |
|||
<th>Floating point representation</th><th>Fixed point representation</th> |
|||
</tr> |
|||
<tr><td>1.25</td><td>5120</td></tr> |
|||
<tr><td>0.75</td><td>3072</td></tr> |
|||
<tr><td>0.2</td><td>819</td></tr> |
|||
<tr><td>21.284</td><td>87179</td></tr> |
|||
<tr><td colspan="2"><center>1.0 = 4096</center></td></tr> |
|||
</tbody></table> |
|||
</center> |
|||
|
|||
<p>Using a scale value of 4096 is most ideal for PlayStation projects not |
|||
only because it provides a good balance between precision and the maximum |
|||
decimal value it can store, alongside allowing fixed point values to be |
|||
rounded and divided quickly with simple bit shift operations and AND masks, |
|||
but also because the Geometry Transformation Engine (GTE) also uses the |
|||
same scale value for some of its registers. Any scale value can be used to |
|||
gain more precision or to increase the decimal range limit. Generally |
|||
a power of two scale value is recommended for performance reasons.</p> |
|||
|
|||
<center> |
|||
<table class="bordered-table"> |
|||
<tbody><tr> |
|||
<td><b>Bits</b></td> |
|||
<td>31</td><td>30</td><td>29</td><td>28</td><td>27</td><td>26</td><td>25</td> |
|||
<td>24</td><td>23</td><td>22</td><td>21</td><td>20</td><td>19</td><td>18</td> |
|||
<td>17</td><td>16</td><td>15</td><td>14</td><td>13</td><td>12</td><td>11</td> |
|||
<td>10</td><td>9</td><td>8</td><td>7</td><td>6</td><td>5</td><td>4</td> |
|||
<td>3</td><td>2</td><td>1</td><td>0</td> |
|||
</tr> |
|||
<tr> |
|||
<td><b>Description</b></td> |
|||
<td>Sign</td> |
|||
<td colspan="19">Decimal (19 bits)</td> |
|||
<td colspan="12">Fractional (12 bits)</td> |
|||
</tr> |
|||
</tbody></table> |
|||
</center> |
|||
|
|||
<p>The table above illustrates a fixed point value with a scale value |
|||
of 4096 in a signed 32-bit integer. As there's only 19 bits available for |
|||
the decimal portion the maximum range for the decimal value is -524288 to |
|||
524287.</p> |
|||
|
|||
|
|||
<h2 id="basics">Fixed Point Arithmetic Basics</h2> |
|||
|
|||
<p>Simple mathematical operations in fixed point such as addition and |
|||
subtraction is not that much different to performing the same operations |
|||
with integers, only values have to be based around the scale value.</p> |
|||
<pre>fixed_value += 4096; // += 1.0 |
|||
fixed_value -= 4096; // -= 1.0 |
|||
fixed_value += 2048; // += 0.5 |
|||
fixed_value -= 6144; // -= 1.5 |
|||
</pre> |
|||
|
|||
<p>For decimal multiplication and divide operations, the value for the |
|||
dividend or multiplicand stays as-is.</p> |
|||
<pre>fixed_value *= 5; // *= 5; |
|||
fixed_value /= 10; // /= 10; |
|||
</pre> |
|||
|
|||
<p>The equation for performing fractional multiplications is a little |
|||
tricky, but still not too complicated.</p> |
|||
<pre>multiplicand = 2048; // multiplicand = 0.5; |
|||
fixed_value = (fixed_value*multiplicand)>>12; // fixed_value *= multiplicand; |
|||
|
|||
multiplicand = 6144; // multiplicand = 1.5; |
|||
fixed_value = (fixed_value*multiplicand)>>12; // fixed_value *= multiplicand; |
|||
</pre> |
|||
|
|||
<p>For fractional divisions, the value will need to be multiplied by the |
|||
scale value and then divided by the dividend. Keep in mind that division by |
|||
zero would still occur if the dividend is zero. |
|||
</p><pre>dividend = 2048; // dividend = 0.5; |
|||
fixed_value = (fixed_value*4096)/dividend; // fixed_value /= dividend; |
|||
|
|||
dividend = 6144; // dividend = 1.5; |
|||
fixed_value = (fixed_value*4096)/dividend; // fixed_value /= dividend; |
|||
</pre> |
|||
|
|||
|
|||
<h2 id="tankcontrols">Implementing Tank Controls with Fixed Point</h2> |
|||
|
|||
<p>As a little exercise, this part of the chapter will go through using fixed |
|||
point math to implement tank controls. The basic jist of this is that instead |
|||
of moving the player position directly by which direction of the D-pad is |
|||
pressed, instead, left and right will adjust the angle the player is facing |
|||
while up and down moves the player forward and backward perpendicular to |
|||
where the player is facing. To do this requires using sine and cosine values |
|||
and conveniently, the GTE libraries of both SDKs feature integer based sine |
|||
and cosine functions which is exactly what's needed for this exercise.</p> |
|||
|
|||
<p>In the official PsyQ or Programmer's Tool SDKs there are two integer based |
|||
sine and cosine functions which are <b>rsin()</b>/<b>rcos()</b> and |
|||
<b>csin()</b>/<b>ccos()</b>. The differences between the two is that |
|||
<b>rsin()</b>/<b>rcos()</b> takes up less code but is slower, whereas |
|||
<b>csin()</b>/<b>ccos()</b> takes up more code but is faster. PSn00bSDK on |
|||
the other hand only has one set of functions called <b>isin()/icos()</b>, |
|||
which are based on a Taylor series implementation which is both small and fast. |
|||
PSn00bSDK provides definitions for <b>rsin()</b>/<b>rcos()</b> and |
|||
<b>csin()</b>/<b>ccos()</b> that simply points to <b>isin()/icos()</b> |
|||
for compatibility with PsyQ / Programmer's Tool projects and sample code.</p><p> |
|||
|
|||
</p><p>These functions also take degrees in a fixed point range of 0 to 4096 |
|||
where 4096 equals to 360 degrees, so a value of 45 degrees will be |
|||
specified as 512. The value returned is also in a fixed point notation |
|||
with a scale of 4096, where 4096 equals to 1.0.</p> |
|||
|
|||
<p>Working from code from the controllers chapter, rewrite the code that |
|||
defines the initial values of the player position to begin at the center |
|||
of the screen. Because the player coordinates will be in fixed point, the |
|||
screen center coordinate must be multiplied by <b>ONE</b>.</p> |
|||
|
|||
<pre>pos_x = ONE*(disp[0].disp.w>>1); |
|||
pos_y = ONE*(disp[0].disp.h>>1); |
|||
</pre> |
|||
|
|||
<p>Then, define a new variable for the player's angle and set the initial |
|||
value to zero.</p> |
|||
|
|||
<pre>int angle; |
|||
|
|||
angle = 0; |
|||
</pre> |
|||
|
|||
<p>The player will be represented as a rotating triangle in this chaper, so |
|||
a simple array of vector coordinates will define the shape of the triangle. |
|||
The triangle will be rotated with, you guessed it, fixed point math as well. |
|||
</p> |
|||
|
|||
<pre>SVECTOR player_tri[] = |
|||
{ |
|||
{ 0, -20, 0 }, |
|||
{ 10, 20, 0 }, |
|||
{ -10, 20, 0 } |
|||
}; |
|||
</pre> |
|||
|
|||
<p>Then ditch the code for sorting <b>TILE</b> and <b>SPRT</b> primitives |
|||
and replace it with the following routine that sorts a rotating triangle.</p> |
|||
<pre>POLY_F3 *tri; |
|||
|
|||
... |
|||
|
|||
// Rotate the triangle coordinates based on the player's angle |
|||
// as well as apply the position |
|||
for( i=0; i<3; i++ ) |
|||
{ |
|||
v[i].vx = (((player_tri[i].vx*ccos( angle )) |
|||
-(player_tri[i].vy*csin( angle )))>>12)+(pos_x>>12); |
|||
v[i].vy = (((player_tri[i].vy*ccos( angle )) |
|||
+(player_tri[i].vx*csin( angle )))>>12)+(pos_y>>12); |
|||
} |
|||
|
|||
// Sort the player triangle |
|||
tri = (POLY_F3*)nextpri; |
|||
setPolyF3( tri ); |
|||
setRGB0( tri, 255, 255, 0 ); |
|||
setXY3( tri, |
|||
v[0].vx, v[0].vy, |
|||
v[1].vx, v[1].vy, |
|||
v[2].vx, v[2].vy ); |
|||
|
|||
addPrim( ot[db], tri ); |
|||
nextpri += sizeof(POLY_F3); |
|||
</pre> |
|||
|
|||
<p>And then replace the input code with the following. If you've written |
|||
something that played like Asteroids in the past, this may look pretty |
|||
familiar.</p> |
|||
<pre>if( !(pad->btn&PAD_UP) ) // test UP |
|||
{ |
|||
pos_x += csin( angle ); |
|||
pos_y -= ccos( angle ); |
|||
} |
|||
else if( !(pad->btn&PAD_DOWN) ) // test DOWN |
|||
{ |
|||
pos_x -= csin( angle ); |
|||
pos_y += ccos( angle ); |
|||
} |
|||
if( !(pad->btn&PAD_LEFT) ) // test LEFT |
|||
{ |
|||
// Turns counter-clockwise |
|||
angle -= 16; |
|||
} |
|||
else if( !(pad->btn&PAD_RIGHT) ) // test RIGHT |
|||
{ |
|||
// Turns clockwise |
|||
angle += 16; |
|||
} |
|||
</pre> |
|||
|
|||
<p>Next is to finally add some text drawing so the player coordinates can be |
|||
displayed on screen, so you can see how fixed point numbers work while |
|||
interacting with the sample program more easily. This can be done with the |
|||
debug font functions provided by <h>libetc</h> or <h>psxetc</h> in both |
|||
PsyQ / Programmer's Tool and PSn00bSDK respectively. These font functions are |
|||
intended for debugging purposes, so they're not fit for drawing things like |
|||
player status with custom fonts and lower case letters.</p> |
|||
|
|||
<p>Start by loading the debug font texture to VRAM using <b>FntLoad()</b>, |
|||
then, initialize a font window using <b>FntOpen()</b>. Ideally, you should |
|||
put these calls inside the <b>init()</b> function.</p> |
|||
|
|||
<pre>// Load the font texture on the upper-right corner of the VRAM |
|||
FntLoad( 960, 0 ); |
|||
|
|||
// Define a font window of 100 characters covering the whole screen |
|||
FntOpen( 0, 8, 320, 224, 0, 100 ); |
|||
</pre> |
|||
|
|||
<p>Text can be printed using <b>FntPrint()</b> which works more or less like |
|||
<b>printf()</b>, only text output is directed to the specified font window. |
|||
The first argument specifies which font window the text should go to, the |
|||
value of which is obtained through the return value of <b>FntOpen()</b>. |
|||
Specifying -1 directs text to the last opened font window. The debug font |
|||
routines can only draw uppercase text, and text color and font cannot be |
|||
customized.</p> |
|||
|
|||
<p>In PsyQ / Programmers tool the first argument can be omitted, but modern |
|||
GNU GCC does not support this convention anymore.</p> |
|||
|
|||
<pre>// Print player coordinates |
|||
FntPrint( -1, "POS_X=%d (%d.%d)\n", pos_x, (pos_x>>12), (pos_x&0xfff) ); |
|||
FntPrint( -1, "POS_Y=%d (%d.%d)\n", pos_y, (pos_y>>12), (pos_y&0xfff) ); |
|||
FntPrint( -1, "ANGLE=%d\n", angle ); |
|||
</pre> |
|||
|
|||
<p>Then to make the text actually appear, call <b>FntFlush()</b> to draw the |
|||
characters 'printed' by <b>FntPrint()</b> and flush the character buffer. |
|||
This should be called immediately before the <b>display()</b> call in the |
|||
sample code.</p> |
|||
|
|||
<pre>// Draw and flush the character buffer |
|||
FntFlush( -1 ); |
|||
</pre> |
|||
|
|||
<p>The finished code should look like the following (the texture stuff |
|||
remains for future samples):</p> |
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <psxetc.h> // Includes some functions that controls the display |
|||
#include <psxgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <psxgpu.h> // GPU library header |
|||
#include <psxapi.h> |
|||
|
|||
#define OTLEN 8 // Ordering table length (recommended to set as a define |
|||
// so it can be changed easily) |
|||
|
|||
DISPENV disp[2]; // Display/drawing buffer parameters |
|||
DRAWENV draw[2]; |
|||
int db = 0; |
|||
|
|||
// PSn00bSDK requires having all u_long types replaced with |
|||
// u_int, as u_long in modern GCC that PSn00bSDK uses defines it as a 64-bit integer. |
|||
|
|||
u_int ot[2][OTLEN]; // Ordering table length |
|||
char pribuff[2][32768]; // Primitive buffer |
|||
char *nextpri; // Next primitive pointer |
|||
|
|||
int tim_mode; // TIM image parameters |
|||
RECT tim_prect,tim_crect; |
|||
int tim_uoffs,tim_voffs; |
|||
|
|||
// Pad stuff |
|||
#define PAD_SELECT 1 |
|||
#define PAD_L3 2 |
|||
#define PAD_R3 4 |
|||
#define PAD_START 8 |
|||
#define PAD_UP 16 |
|||
#define PAD_RIGHT 32 |
|||
#define PAD_DOWN 64 |
|||
#define PAD_LEFT 128 |
|||
#define PAD_L2 256 |
|||
#define PAD_R2 512 |
|||
#define PAD_L1 1024 |
|||
#define PAD_R1 2048 |
|||
#define PAD_TRIANGLE 4096 |
|||
#define PAD_CIRCLE 8192 |
|||
#define PAD_CROSS 16384 |
|||
#define PAD_SQUARE 32768 |
|||
|
|||
typedef struct _PADTYPE |
|||
{ |
|||
unsigned char stat; |
|||
unsigned char len:4; |
|||
unsigned char type:4; |
|||
unsigned short btn; |
|||
unsigned char rs_x,rs_y; |
|||
unsigned char ls_x,ls_y; |
|||
} PADTYPE; |
|||
|
|||
u_char padbuff[2][34]; |
|||
|
|||
// For the player triangle |
|||
SVECTOR player_tri[] = { |
|||
{ 0, -20, 0 }, |
|||
{ 10, 20, 0 }, |
|||
{ -10, 20, 0 } |
|||
}; |
|||
|
|||
void display() { |
|||
|
|||
DrawSync(0); // Wait for any graphics processing to finish |
|||
|
|||
VSync(0); // Wait for vertical retrace |
|||
|
|||
PutDispEnv(&disp[db]); // Apply the DISPENV/DRAWENVs |
|||
PutDrawEnv(&draw[db]); |
|||
|
|||
SetDispMask(1); // Enable the display |
|||
|
|||
DrawOTag(ot[db]+OTLEN-1); // Draw the ordering table |
|||
|
|||
db = !db; // Swap buffers on every pass (alternates between 1 and 0) |
|||
nextpri = pribuff[db]; // Reset next primitive pointer |
|||
|
|||
} |
|||
|
|||
// Texture upload function |
|||
void LoadTexture(u_int *tim, TIM_IMAGE *tparam) { |
|||
|
|||
// Read TIM parameters (PsyQ) |
|||
//OpenTIM(tim); |
|||
//ReadTIM(tparam); |
|||
|
|||
// Read TIM parameters (PSn00bSDK) |
|||
GetTimInfo(tim, tparam); |
|||
|
|||
// Upload pixel data to framebuffer |
|||
LoadImage(tparam->prect, tparam->paddr); |
|||
DrawSync(0); |
|||
|
|||
// Upload CLUT to framebuffer if present |
|||
if( tparam->mode & 0x8 ) { |
|||
|
|||
LoadImage(tparam->crect, tparam->caddr); |
|||
DrawSync(0); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
void loadstuff(void) { |
|||
|
|||
TIM_IMAGE my_image; // TIM image parameters |
|||
|
|||
extern u_int tim_my_image[]; |
|||
|
|||
// Load the texture |
|||
LoadTexture(tim_my_image, &my_image); |
|||
|
|||
// Copy the TIM coordinates |
|||
tim_prect = *my_image.prect; |
|||
tim_crect = *my_image.crect; |
|||
tim_mode = my_image.mode; |
|||
|
|||
// Calculate U,V offset for TIMs that are not page aligned |
|||
tim_uoffs = (tim_prect.x%64)<<(2-(tim_mode&0x3)); |
|||
tim_voffs = (tim_prect.y&0xff); |
|||
|
|||
} |
|||
|
|||
// To make main look tidy, init stuff has to be moved here |
|||
void init(void) { |
|||
|
|||
// Reset graphics |
|||
ResetGraph(0); |
|||
|
|||
// First buffer |
|||
SetDefDispEnv(&disp[0], 0, 0, 320, 240); |
|||
SetDefDrawEnv(&draw[0], 0, 240, 320, 240); |
|||
// Second buffer |
|||
SetDefDispEnv(&disp[1], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw[1], 0, 0, 320, 240); |
|||
|
|||
draw[0].isbg = 1; // Enable clear |
|||
setRGB0(&draw[0], 63, 0, 127); // Set clear color (dark purple) |
|||
draw[1].isbg = 1; |
|||
setRGB0(&draw[1], 63, 0, 127); |
|||
|
|||
nextpri = pribuff[0]; // Set initial primitive pointer address |
|||
|
|||
// load textures and possibly other stuff |
|||
loadstuff(); |
|||
|
|||
// set tpage of lone texture as initial tpage |
|||
draw[0].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
draw[1].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
|
|||
// apply initial drawing environment |
|||
PutDrawEnv(&draw[!db]); |
|||
|
|||
// Initialize the pads |
|||
InitPAD( padbuff[0], 34, padbuff[1], 34 ); |
|||
|
|||
// Begin polling |
|||
StartPAD(); |
|||
|
|||
// To avoid VSync Timeout error, may not be defined in PsyQ |
|||
ChangeClearPAD( 1 ); |
|||
|
|||
// Load the font texture on the upper-right corner of the VRAM |
|||
FntLoad( 960, 0 ); |
|||
|
|||
// Define a font window of 100 characters covering the whole screen |
|||
FntOpen( 0, 8, 320, 224, 0, 100 ); |
|||
|
|||
} |
|||
|
|||
int main() { |
|||
|
|||
int i; |
|||
int pos_x,pos_y,angle; |
|||
PADTYPE *pad; |
|||
POLY_F3 *tri; |
|||
SVECTOR v[3]; |
|||
|
|||
TILE *tile; // Pointer for TILE |
|||
SPRT *sprt; // Pointer for SPRT |
|||
|
|||
// Init stuff |
|||
init(); |
|||
|
|||
pos_x = ONE*(disp[0].disp.w>>1); |
|||
pos_y = ONE*(disp[0].disp.h>>1); |
|||
angle = 0; |
|||
|
|||
while(1) { |
|||
|
|||
// Parse controller input |
|||
pad = (PADTYPE*)padbuff[0]; |
|||
|
|||
// Only parse inputs when a controller is connected |
|||
if( pad->stat == 0 ) |
|||
{ |
|||
// Only parse when a digital pad, |
|||
// dual-analog and dual-shock is connected |
|||
if( ( pad->type == 0x4 ) || |
|||
( pad->type == 0x5 ) || |
|||
( pad->type == 0x7 ) ) |
|||
{ |
|||
if( !(pad->btn&PAD_UP) ) // test UP |
|||
{ |
|||
pos_x += csin( angle ); |
|||
pos_y -= ccos( angle ); |
|||
} |
|||
else if( !(pad->btn&PAD_DOWN) ) // test DOWN |
|||
{ |
|||
pos_x -= csin( angle ); |
|||
pos_y += ccos( angle ); |
|||
} |
|||
if( !(pad->btn&PAD_LEFT) ) // test LEFT |
|||
{ |
|||
angle -= 16; |
|||
} |
|||
else if( !(pad->btn&PAD_RIGHT) ) // test RIGHT |
|||
{ |
|||
angle += 16; |
|||
} |
|||
} |
|||
} |
|||
|
|||
ClearOTagR(ot[db], OTLEN); // Clear ordering table |
|||
|
|||
// Rotate the triangle coordinates based on the player's angle |
|||
// as well as apply the position |
|||
for( i=0; i<3; i++ ) |
|||
{ |
|||
v[i].vx = (((player_tri[i].vx*icos( angle )) |
|||
-(player_tri[i].vy*csin( angle )))>>12)+(pos_x>>12); |
|||
v[i].vy = (((player_tri[i].vy*icos( angle )) |
|||
+(player_tri[i].vx*csin( angle )))>>12)+(pos_y>>12); |
|||
} |
|||
|
|||
// Sort the player triangle |
|||
tri = (POLY_F3*)nextpri; |
|||
setPolyF3( tri ); |
|||
setRGB0( tri, 255, 255, 0 ); |
|||
setXY3( tri, |
|||
v[0].vx, v[0].vy, |
|||
v[1].vx, v[1].vy, |
|||
v[2].vx, v[2].vy ); |
|||
addPrim( ot[db], tri ); |
|||
nextpri += sizeof(POLY_F3); |
|||
|
|||
// Print player coordinates |
|||
FntPrint( -1, "POS_X=%d (%d.%d)\n", pos_x, (pos_x>>12), (pos_x&0xfff) ); |
|||
FntPrint( -1, "POS_Y=%d (%d.%d)\n", pos_y, (pos_y>>12), (pos_y&0xfff) ); |
|||
FntPrint( -1, "ANGLE=%d\n", angle ); |
|||
|
|||
// Draw and flush the character buffer |
|||
FntFlush( -1 ); |
|||
|
|||
// Update the display |
|||
display(); |
|||
|
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
|
|||
<p>Compile and execute the code and you should get a triangle that controls |
|||
more or less like a tank. Press the left and right directional buttons to |
|||
turn the triangle while pressing up and down moves the triangle forwards and |
|||
backward perpendicular to where the triangle is pointing.</p> |
|||
|
|||
<center> |
|||
<img src="Chapter%201.5%20Fixed%20point%20Math_files/tankmove.png"> |
|||
</center> |
|||
|
|||
|
|||
<h2 id="asteroids">Asteroids Style Physics with Fixed Point</h2> |
|||
|
|||
<p>Now to make the tank controls sample a little more interesting by making |
|||
it control like an Asteroids or Spacewar game. Basically, instead of |
|||
accumulating the player coordinates directly with values based on the |
|||
player's angle you accumulate them to a velocity vector, which in turn |
|||
accumulates on the player's coordinates. This way, simple momentum based |
|||
physics are archieved.</p> |
|||
|
|||
<p>This can be done by implementing some changes to the last sample. Start |
|||
by adding variables in <b>main()</b> that'll be used to store the player's |
|||
velocity coordinates.</p> |
|||
|
|||
<pre>int vel_x,vel_y; |
|||
|
|||
... |
|||
|
|||
// just to make sure they don't contain garbage |
|||
vel_x = 0; |
|||
vel_y = 0; |
|||
</pre> |
|||
|
|||
<p>Next, modify some of the pad code to accumulate player movement |
|||
towards the velocity variables instead of the player's coordinates. |
|||
Put some bit shifts that divides the sin/cos values by 8 otherwise |
|||
the 'ship' will accelerate too quickly.</p> |
|||
|
|||
<pre>if( !(pad->btn&PAD_UP) ) // test UP |
|||
{ |
|||
vel_x += csin( angle )>>3; |
|||
vel_y -= ccos( angle )>>3; |
|||
} |
|||
else if( !(pad->btn&PAD_DOWN) ) // test DOWN |
|||
{ |
|||
vel_x -= csin( angle )>>3; |
|||
vel_y += ccos( angle )>>3; |
|||
} |
|||
</pre> |
|||
|
|||
<p>Immediately after the pad code add a few lines that accumulates the |
|||
velocity coordinates to the player's coordinates.</p> |
|||
|
|||
<pre>// accumulate player coordinates by its velocity |
|||
pos_x += vel_x; |
|||
pos_y += vel_y; |
|||
</pre> |
|||
|
|||
<p>And to keep the player from going off-screen, place the following lines |
|||
immediately after the above code to wrap the player's coordinates when they |
|||
go off-screen.</p> |
|||
|
|||
<pre>// wrap player coordinates from going off-screen |
|||
if( (pos_x>>12) < 0 ) |
|||
{ |
|||
pos_x += (320<<12); |
|||
} |
|||
if( (pos_x>>12) > 320 ) |
|||
{ |
|||
pos_x -= (320<<12); |
|||
} |
|||
if( (pos_y>>12) < 0 ) |
|||
{ |
|||
pos_y += (240<<12); |
|||
} |
|||
if( (pos_y>>12) > 240 ) |
|||
{ |
|||
pos_y -= (240<<12); |
|||
} |
|||
</pre> |
|||
|
|||
<p>Then place some additional <b>FntPrint()</b> calls that displays the |
|||
values from the velocity variables. You'll also need to increase the |
|||
character buffer size of the <b>FntOpen()</b> call (the last argument) |
|||
from 100 to 150.</p> |
|||
|
|||
<pre>FntPrint( -1, "VEL_X=%d (%d.%d)\n", vel_x, (vel_x>>12), (vel_x&0xfff) ); |
|||
FntPrint( -1, "VEL_Y=%d (%d.%d)\n", vel_y, (vel_y>>12), (vel_y&0xfff) ); |
|||
</pre> |
|||
|
|||
<p>Compile the sample demo and the triangle should behave a lot like an |
|||
Asteroids ship.</p> |
|||
|
|||
<center> |
|||
<img src="Chapter%201.5%20Fixed%20point%20Math_files/velocitymove.png"> |
|||
</center> |
|||
|
|||
<p>If you want velocity to slowly diminish overtime, add the following |
|||
lines just before the velocity vectors are accumulated to the player |
|||
coordinates. It also acts as a velocity constraint as well.</p> |
|||
|
|||
<pre>// equivalent to multiplying each axis by 0.9765625 |
|||
vel_x = (vel_x*4000)>>12; |
|||
vel_y = (vel_y*4000)>>12; |
|||
</pre> |
|||
|
|||
|
|||
<h2 id="spriterot">Bonus: Fixed Point Sprite Rotation</h2> |
|||
|
|||
<p>Since it is something new programmers would find incredibly handy and to |
|||
show off some of what the 32-bit console can do, especially for PSn00bSDK folk |
|||
as it does not have an equivalent to libgs, here's a fixed point based sprite |
|||
rotation and scaling routine that draws a rotated and scaled sprite with a |
|||
single quad. The math for rotation is more or less the same as how the player |
|||
triangle is rotated.</p> |
|||
|
|||
<pre>void sortRotSprite( int x, int y, int pw, int ph, int angle, int scale ) |
|||
{ |
|||
POLY_FT4 *quad; |
|||
SVECTOR s[4]; |
|||
SVECTOR v[4]; |
|||
|
|||
int i,cx,cy; |
|||
|
|||
// calculate the pivot point (center) of the sprite |
|||
cx = pw>>1; |
|||
cy = ph>>1; |
|||
|
|||
// increment by 0.5 on the bottom and right coords so scaling |
|||
// would increment a bit smoother |
|||
s[0].vx = -(((pw*scale)>>12)-cx); |
|||
s[0].vy = -(((ph*scale)>>12)-cy); |
|||
|
|||
s[1].vx = (((pw*scale)+2048)>>12)-cx; |
|||
s[1].vy = s[0].vy; |
|||
|
|||
s[2].vx = -(((pw*scale)>>12)-cx); |
|||
s[2].vy = (((ph*scale)+2048)>>12)-cy; |
|||
|
|||
s[3].vx = (((pw*scale)+2048)>>12)-cx; |
|||
s[3].vy = s[2].vy; |
|||
|
|||
// a simple but pretty effective optimization trick |
|||
cx = ccos( angle ); |
|||
cy = csin( angle ); |
|||
|
|||
// calculate rotated sprite coordinates |
|||
for( i=0; i<4; i++ ) |
|||
{ |
|||
v[i].vx = (((s[i].vx*cx) |
|||
-(s[i].vy*cy))>>12)+x; |
|||
v[i].vy = (((s[i].vy*cx) |
|||
+(s[i].vx*cy))>>12)+y; |
|||
} |
|||
|
|||
// initialize the quad primitive for the sprite |
|||
quad = (POLY_FT4*)nextpri; |
|||
setPolyFT4( quad ); |
|||
|
|||
// set CLUT and tpage to the primitive |
|||
setTPage( quad, tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
setClut( quad, tim_crect.x, tim_crect.y ); |
|||
|
|||
// set color, screen coordinates and texture coordinates of primitive |
|||
setRGB0( quad, 128, 128, 128 ); |
|||
setXY4( quad, |
|||
v[0].vx, v[0].vy, |
|||
v[1].vx, v[1].vy, |
|||
v[2].vx, v[2].vy, |
|||
v[3].vx, v[3].vy ); |
|||
setUVWH( quad, tim_uoffs, tim_voffs, pw, ph ); |
|||
|
|||
// add it to the ordering table |
|||
addPrim( ot[db], quad ); |
|||
nextpri += sizeof(POLY_FT4); |
|||
|
|||
} |
|||
</pre> |
|||
|
|||
<p>By this point, it should be easy to figure out how to use this function |
|||
in the sample above. The <i>angle</i> and <i>scale</i> arguments are of a |
|||
fixed point notation, where 4096 is 360 degrees on the former and 4096 is |
|||
1.0 on the latter.</p> |
|||
|
|||
<center> |
|||
<img src="Chapter%201.5%20Fixed%20point%20Math_files/rotscalesprite.png"> |
|||
</center> |
|||
|
|||
<h2 id="limitations">Limitations of Fixed Point Math</h2> |
|||
|
|||
<p>One limitation that becomes apparent when performing 32-bit fixed point |
|||
math arithmetic is when performing fractional multiplication operations with |
|||
large fixed point values due to the C compiler usually always performing |
|||
multiplication and bit shifting operations with 32-bit registers, as |
|||
multiplying a large fixed point value by a large fixed point multiplicand |
|||
will likely exceed the capacity of a 32-bit word, yielding a faulty |
|||
result.</p> |
|||
|
|||
<p>The MIPS R3000 CPU of the PlayStation can actually return a 64-bit |
|||
multiplication result, but the C compiler doesn't really make use of this |
|||
trait when performing multiplication operations with 32-bit integers. So the |
|||
only way to effectively take advantage of this is to use some in-line |
|||
assembly code. Should be pretty self explanatory on how and where it should |
|||
be used.</p> |
|||
|
|||
<pre>/* in-line assembly macro for performing multiplication */ |
|||
/* operations with 12-bit fractions. Uses what is effectively */ |
|||
/* 64-bit maths with both hi and lo result registers to avoid */ |
|||
/* overflow bugs when using 32-bit maths. */ |
|||
/* */ |
|||
/* Performs r2 = ( r0 * r1 )>>12 with 64-bit arithmetic */ |
|||
/* */ |
|||
#define mult12( r0, r1, r2 ) __asm__ volatile ( \ |
|||
"mult %1, %0;" /* multiply values (small * large is faster) */\ |
|||
"mflo $t0;" /* retrieve the 64-bit result in two regs */\ |
|||
"mfhi $t1;" \ |
|||
"srl $t0, 12;" /* equivalent to dividing LO by 4096 */\ |
|||
"and $t1, 0x0fff;" /* mask HI result to fit in upper 12 bits of */\ |
|||
"sll $t1, 20;" /* LO result, then shift bits to position */\ |
|||
"or $t0, $t1;" /* combine the bits */\ |
|||
"sw $t0, ( %2 );" /* store the result to r2 */\ |
|||
: \ |
|||
: "r"( r0 ), "r"( r1 ), "r"( r2 ) \ |
|||
: "lo", "hi", "t0", "t1", "memory" ) |
|||
</pre> |
|||
|
|||
<p>Though naturally, fixed point math can't really be as precise as floating |
|||
point math in certain operations. You can try increasing precision by |
|||
increasing the base value, alloting more bits for the fractional part of a |
|||
fixed point value, but there will still be something rough about it.</p> |
|||
|
|||
|
|||
<h2 id="conclusion">Conclusion and Further Reading</h2> |
|||
|
|||
<p>This chapter only really covers some pretty basic but highly essential math |
|||
operations with fixed point math, but it should be enough to get you started |
|||
in learning the practice. Interestingly fixed point math is still somewhat |
|||
talked about around the modern Internet, so you may want to look around for |
|||
those for further reading if need-be.</p> |
|||
|
|||
<hr> |
|||
<table width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left"><a href="http://lameguy64.net/tutorials/pstutorials/chapter1/4-controllers.html">Previous</a></td> |
|||
<td width="20%" align="center"><a href="http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"><a href="http://lameguy64.net/tutorials/pstutorials/chapter1/6-cdreading.html">Next</a></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
|
|||
</body></html> |
|||
@ -0,0 +1,49 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
@ -0,0 +1,807 @@ |
|||
<html><head> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%201.6%20Using%20the%20CD-ROM_files/style.css"> |
|||
<title>Chapter 1.6: Using the CD-ROM</title> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
|||
</head> |
|||
<body> |
|||
|
|||
<h1>Chapter 1.6: Using the CD-ROM</h1> |
|||
|
|||
<p>So you've managed to make it this far in this tutorial series and have |
|||
wrapped your head around uploading textures to VRAM, drawing sprite |
|||
primitives with the GPU, handling controller input and rotating sprites |
|||
using fixed-point integer math, you should be good to go at making a simple |
|||
game with the knowledge you've gained so far. However, there's one more thing |
|||
to learn that's very important to know in this endeavor before going forward |
|||
and that is using the CD-ROM.</p> |
|||
|
|||
<p>The most obvious use of the CD-ROM drive on the PlayStation is, well, to |
|||
load data files from of course. Such files range from texture images, to |
|||
level data and even your program executable that the console loads during |
|||
the boot process. You can only go so far by including resources into your |
|||
PS-EXE as the console only has 2 megabytes worth of RAM, and more |
|||
importantly, they take up memory space that cannot be reclaimed even when |
|||
they are no longer needed (ie. texture images).</p> |
|||
|
|||
<p>This chapter goes over the basic usage and operation of the CD-ROM library |
|||
for reading files from the CD-ROM.</p> |
|||
|
|||
<p><b>Compatible with PSn00bSDK:</b> Yes</p> |
|||
|
|||
<h2>Tutorial Index</h2> |
|||
<ul> |
|||
<li><a href="#workins">Workings of the CD-ROM</a></li> |
|||
<li><a href="#waystoaccess">Ways of Accessing the CD-ROM</a></li> |
|||
<li><a href="#usinglib">Using the CD-ROM Library</a></li> |
|||
<li><a href="#implementation">Implementation</a></li> |
|||
<li><a href="#makecd">Creating the CD Image</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="workins">Workings of the CD-ROM</h2> |
|||
|
|||
<p>Before going into the know-abouts on using the CD-ROM we shall first |
|||
look into a brief explanation of how the CD-ROM format works, as |
|||
understanding some of the inner workings of the format will aid you |
|||
greatly in understanding the CD-ROM drive as you develop software for |
|||
the PlayStation.</p> |
|||
|
|||
<h3>CD-ROM Structure</h3> |
|||
|
|||
<p>A CD-ROM typically consists of a Table-of-Contents or TOC |
|||
and a huge spiral track that spans the entire surface of the disc containing |
|||
sectors of binary data running along the track. The TOC contains information |
|||
about the location of tracks written on the disc, their pregap and their |
|||
type of track, a track in this case being the track number to your favorite |
|||
song in a music CD. The TOC would also contain information of the next |
|||
writable location in multi-session discs, which would in turn contain |
|||
another TOC of the next session but this only really applies to CD-R |
|||
discs.</p> |
|||
|
|||
<p>PlayStation game discs typically contain only one track, with the exception |
|||
of games, usually early titles, using Red Book CD Audio tracks for music |
|||
immediately after the first data track of the disc.</p> |
|||
|
|||
<h3>CD-ROM Sectors</h3> |
|||
|
|||
<p>A CD-ROM sector is a small data block of 2352 bytes but this only |
|||
applies to plain CD audio tracks, as the usable sector size is reduced |
|||
to 2048 bytes for data storage (ie. files). The remaining space of the |
|||
CD-ROM sector is taken up by sync and address bytes used to allow for |
|||
precise logical block addressing of the disc, alongside error detection |
|||
and correcting codes to help maintain data integrity of each data sector. |
|||
This sector format is known as Mode1, with a similar format used by the |
|||
PlayStation being Mode2/Form1 from the CD-ROM XA specification as used |
|||
by the Philips CD-i.</p> |
|||
|
|||
<p>As far as the PlayStation is concerned, the console only reads |
|||
the data part of the sector on data reads, with the sync/address |
|||
and EDC/ECC correction handled transparently by the hardware |
|||
unless instructed to ignore EDC/ECC correction on data reads or |
|||
to read whole sectors including their EDC/ECC data.</p> |
|||
|
|||
<h3>CD-ROM XA Extensions</h3> |
|||
|
|||
<p>As the PlayStation inherits the CD-ROM XA features from the CD-i as Sony |
|||
co-developed the Green Book standard with Philips, the console supports |
|||
playing back of special ADPCOM compressed audio tracks, most commonly known |
|||
as XA audio.</p> |
|||
|
|||
<p>XA audio are basically special audio tracks compressed using ADPCM, with |
|||
a maximum sample rate of 37.8KHz mono or stereo. Unlike regular Red Book CD |
|||
Audio tracks XA audio tracks are interleaved with eight different audio |
|||
tracks at once (the interleave can be doubled, tripled and quadrupled by |
|||
using mono and/or 18.9KHz sample rate) and is played at double the speed of |
|||
plain CD Audio. However, the hardware only supports playing one audio |
|||
channel at a time.</p> |
|||
|
|||
<p>This has some advantages, for one the drive does not need to change speed |
|||
when going from audio playback to data reading which can help improve load |
|||
times. Secondly, XA audio tracks take up less space overall especially when |
|||
the XA audio data is laid out properly (ie. all audio channels are of roughly |
|||
the same length to one another). Thirdly, XA audio data can be interleaved |
|||
with data sectors, and is used for video playback. The Data/XA Audio interleave |
|||
also explains why some files on a PlayStation game disc (usually .STR video |
|||
files) cannot be accessed directly under most computer operating systems, |
|||
usually resulting in read errors.</p> |
|||
|
|||
<p>However, XA audio has one downside and that is it tends to skip during |
|||
normal playback more than when playing back regular CD Audio tracks.</p> |
|||
|
|||
<p>There is one more feature of XA audio that's seldom used and that is |
|||
channel switching during playback. This would be useful for adding dynamic |
|||
music to a game by switching to different channels of different tangents |
|||
of a level theme depending on the area the player is currently at. One game |
|||
that makes use of this feature is Klonoa: Door to Phantomile.</p> |
|||
|
|||
<h3>The 650MB Limit</h3> |
|||
|
|||
<p>Even though the PlayStation can read 700MB discs it cannot read more |
|||
than 650MB of the disc as the console's CD-ROM controller does not take |
|||
larger discs into account, as the console was designed before such discs |
|||
ever existed and the original CD-ROM specification specifies 650MB as the |
|||
standard capacity.</p> |
|||
|
|||
<h2 id="waystoaccess">Ways of Accessing the CD-ROM</h2> |
|||
|
|||
<p>There are two possible methods for accessing the CD-ROM of the PlayStation |
|||
that will work on both PsyQ/Programmer's Tool and PSn00bSDK. The first method |
|||
and one that is seldom used is the CD-ROM functions included in the console's |
|||
BIOS, which consists of calling <b>_96_init()</b> to initialize the BIOS |
|||
CD-ROM subsystem and using the BIOS file I/O functions such as <b>open()</b> |
|||
and <b>read()</b> with the <h>cdrom:</h> device name. Whilst this method is |
|||
technically the most efficient option as it does not introduce any code |
|||
overhead to your PlayStation project as the functions already reside in the |
|||
console itself, the BIOS CD-ROM functions are rather limited and in a good |
|||
number of cases, unstable.</p> |
|||
|
|||
<p>For one, calling <b>_96_init()</b> clears all but the DMA channel for the |
|||
CD-ROM controller, breaking the GPU library unless you call the function before |
|||
<b>ResetGraph()</b>. The BIOS functions are also quite slow and does not |
|||
support asynchronous reads, even though the hardware itself clearly supports |
|||
such operations. It does not even support playing CD Audio nor XA audio tracks |
|||
directly, so a different method is often most desired.</p> |
|||
|
|||
<p>The other, more preferable method is to use the CD-ROM library called |
|||
<h>libcd</h> in PsyQ/Programmer's Tool and <h>psxcd</h> in PSn00bSDK |
|||
respectively. Not only is it faster and more stable than the BIOS CD-ROM |
|||
functions at the cost of some overhead, but it also offers greater control |
|||
of the CD-ROM hardware as well. Playing CD Audio and XA audio included.</p> |
|||
|
|||
<h2 id="usinglib">Using the CD-ROM Library</h2> |
|||
|
|||
<p>Using the CD-ROM library is quite simple in principle. The first thing |
|||
to be done is to initialize the CD-ROM library by calling the function |
|||
<b>CdInit()</b>. This function not only initializes the CD-ROM hardware |
|||
but also the CD-ROM library itself.</p> |
|||
|
|||
<h3 id="cdinit">Initializing the CD-ROM</h3> |
|||
|
|||
<p>After calling <b>ResetGraph()</b> in your init routine you can then call |
|||
<b>CdInit()</b> to initialize the CD-ROM library.</p> |
|||
|
|||
<pre>int CdInit(void) |
|||
</pre> |
|||
|
|||
<p>The behavior of this function is very identical in both SDKs, but the |
|||
PsyQ/Programmers Tool implementation insists that a CD must be inserted |
|||
otherwise the function will output a lot of error messages to stdout and |
|||
fail to initialize. PSn00bSDK's implementation does not throw errors |
|||
when no disc is inserted, as it is written with utility style programs |
|||
that don't always need to read the disc in mind.</p> |
|||
|
|||
<p>After calling this function, all CD-ROM functions exposed by the library |
|||
should be usable.</p> |
|||
|
|||
<h3 id="locatefile">Locating a File</h3> |
|||
|
|||
<p>Now that the CD-ROM library is initialized the next step is to locate a |
|||
file on the disc to be read. Unlike the BIOS CD-ROM functions, the CD-ROM |
|||
library does not have a concept of file handles and instead, files are |
|||
read directly from their logical position on the disc. Conveniently, no |
|||
files on a CD-ROM are fragmented so file read operations from the CD-ROM |
|||
are quite simple and pretty straight forward.</p> |
|||
|
|||
<p>Locating a file on the disc is done by using <b>CdSearchFile()</b>.</p> |
|||
|
|||
<pre>CdlFILE* CdSearchFile(const char *filename, CdlFILE *loc) |
|||
</pre> |
|||
|
|||
<p>This function will search the CD-ROM file system for the file specified |
|||
by <i>filename</i> and stores information about the file, such as it's |
|||
logical position and file size, to a <b>CdlFILE</b> struct specified by |
|||
<i>loc</i>. This information is all we need to read a file from the disc. |
|||
The file name must contain an absolute path from the root directory of |
|||
the disc as the CD-ROM library has no concept of current directories. The |
|||
file path must additionally end with a file version identifier, usually |
|||
<h>;1</h>.</p> |
|||
|
|||
<p>The return value is just a pointer to the struct specified by <i>loc</i>, |
|||
but NULL is returned if the file name specified does not exist.</p> |
|||
|
|||
<h3 id="readfile">Reading a File</h3> |
|||
|
|||
<p>Now that the file we want to read has been located, the next logical step |
|||
is to read it's contents. This is done by using two CD-ROM functions; |
|||
<b>CdControl()</b> and <b>CdRead()</b>.</p> |
|||
|
|||
<p><b>CdControl()</b> is kind of a multi-purpose function as it is used |
|||
to issue raw commands directly to the console's CD-ROM controller and |
|||
can be used to make the controller do all kinds of things including |
|||
CD audio playback, but this will be covered in greater detail at a later |
|||
chapter.</p> |
|||
|
|||
<p>For this instance, we'll be using <b>CdControl()</b> to issue a |
|||
<b>CdlSetloc</b> command to the CD-ROM controller with the location of the |
|||
file we just located.</p> |
|||
|
|||
<pre>int CdControl(u_char com, u_char *param, u_char *result); |
|||
</pre> |
|||
|
|||
<p><i>com</i> specifies the command to be issued (<b>CdlSetloc</b> in this |
|||
case) while <i>param</i> should be a pointer to the <i>loc</i> element in |
|||
the <b>CdlFILE</b> struct we obtained from the <b>CdSearchFile()</b> call |
|||
earlier. <i>result</i> can be ignored in this instance so NULL can be |
|||
specified for that argument. <i>result</i> is where return data from the |
|||
CD-ROM controller would be stored to if a small buffer is specified.</p> |
|||
|
|||
<p>The reason we must issue a <b>CdlSetloc</b> command is it sets the |
|||
target location for a read, seek or play operation. The CD-ROM hardware |
|||
does not yet move it's optical pickup when <b>CdlSetloc</b> is issued |
|||
alone, seeking only occurs when either of the aforementioned disc |
|||
operations have been issued and that a target location set by issuing |
|||
<b>CdlSetloc</b> was set prior.</p> |
|||
|
|||
<p>And finally, we can now start a read operation by calling the |
|||
<b>CdRead()</b> function.</p> |
|||
|
|||
<pre>int CdRead(int sectors, unsigned int *buf, int mode) |
|||
</pre> |
|||
|
|||
<p>As the name says it all, this function starts a data read operation from |
|||
the disc starting from the logical position specified by a previously issued |
|||
<b>CdlSetloc</b> command. <i>sectors</i> specifies the number of sectors to |
|||
read from the disc, the exact number can be determined by taking the |
|||
<i>size</i> field in the <b>CdlFILE</b> struct, adding it by 2047 then |
|||
divide by 2048. More will be explained why it had to be computed that way |
|||
later. The sectors read are then stored to <i>buf</i>, which |
|||
must point to a buffer large enough to contain all the sectors to be read. |
|||
<i>mode</i> specifies the CD-ROM mode to use for the read operation, usually |
|||
<b>CdlModeSpeed</b> is needed for all file read operations so data is read |
|||
at full speed.</p> |
|||
|
|||
<p>If you haven't guessed from the brief explanation of the operation of |
|||
CD-ROMs earlier in this chapter, each sector is 2048 bytes long. And because |
|||
<b>CdRead()</b> only reads in sector units you can only read data in |
|||
multiples of 2048 bytes. The logical position of files stored on the CD-ROM |
|||
are also addressed in multiples of 2048 bytes.</p> |
|||
|
|||
<p>The BIOS CD-ROM functions are also limited to reading files in units of |
|||
2048 bytes and file seeks are limited to multiples of 2048 bytes as well. |
|||
Because of this, it is much faster to just load the entirety of a file into |
|||
memory and parse the file from there, especially as performing several small |
|||
seeks and read operations would be quite slow, even moreso as the |
|||
PlayStation's CD-ROM hardware doesn't have very fast access times.</p> |
|||
|
|||
<p>Once <b>CdRead()</b> has been called and the PlayStation's optical pickup |
|||
seeks to the file's location and begins reading data, the memory buffer |
|||
specified for <i>buf</i> should start filling with data from the file being |
|||
read. However, the <b>CdRead()</b> function finishes almost immediately and |
|||
the buffer may not yet contain the file you're reading yet, so another step |
|||
is required to make sure the buffer is filled with all the contents of the |
|||
file you want to load.</p> |
|||
|
|||
<pre>int CdReadSync(int mode, unsigned char *result) |
|||
</pre> |
|||
|
|||
<p>This function will wait until the <b>CdRead()</b> operation is actually |
|||
completed if <i>mode</i> is set to zero. If it is non-zero the function |
|||
returns the number of sectors remaining in the read operation. This is |
|||
useful if you want to have a animated loading screen or some such. |
|||
If a buffer is specified in <i>result</i> the most recent CD-ROM status |
|||
is written to that buffer, but it can be left NULL if not needed.</p> |
|||
|
|||
<p>The asynchronous nature of the <b>CdRead()</b> function may be utilized |
|||
for implemented animated loading screens and such.</p> |
|||
|
|||
<h3>Finished Routine</h3> |
|||
|
|||
<p>With all that taken in, a simple CD-ROM read routine should like this.</p> |
|||
|
|||
<pre>CdlFILE filePos; |
|||
int numsecs; |
|||
char *buff; |
|||
|
|||
/* locate the file on the CD */ |
|||
if( CdSearchFile( &filePos, "\\TEXTURE.TIM;1" ) == NULL ) |
|||
{ |
|||
/* print error message if file not found */ |
|||
printf( "File was not found." ); |
|||
} |
|||
else |
|||
{ |
|||
/* calculate number of sectors to read for the file */ |
|||
numsecs = (filePos.size+2047)/2048; |
|||
|
|||
/* allocate buffer for the file */ |
|||
buff = (char*)malloc( 2048*numsecs ); |
|||
|
|||
/* set read target to the file */ |
|||
CdControl( CdlSetloc, (u_char*)&filePos.loc, 0 ); |
|||
|
|||
/* start read operation */ |
|||
CdRead( numsecs, (u_long*)buff, CdlModeSpeed ); |
|||
|
|||
/* wait until the read operation is complete */ |
|||
CdReadSync( 0, 0 ); |
|||
} |
|||
</pre> |
|||
|
|||
<p>You may notice that the file size has to be incremented by 2047 |
|||
then divided by 2048. This is to make sure that the sector count calculated |
|||
would cover the entirety of a file that is not a perfect multiple of 2048 |
|||
bytes. If the file to be read were like 1536 bytes, the whole file would be |
|||
read as one whole sector with the excess bytes being nothing more but |
|||
padding.</p> |
|||
|
|||
<p>You also have to remember that data reads from the CD are still multiples |
|||
of 2048 bytes, so the read buffer must be allocated in multiples of 2048 bytes |
|||
to avoid buffer overflow bugs, which would in turn trash the memory heap.</p> |
|||
|
|||
<h2 id="implementation">Implementation</h2> |
|||
|
|||
<p>To keep things simple we'll just implement it on top of the exisitng |
|||
sample program from the last chapter. Basically instead of reading the |
|||
sample texture from an array we'll load the texture file from the CD-ROM. |
|||
This can be quickly implemented by implementing our CD-ROM file read routine |
|||
as a nice little function.</p> |
|||
|
|||
<pre>char *loadfile( const char *filename ) |
|||
{ |
|||
CdlFILE filePos; |
|||
int numsecs; |
|||
char *buff; |
|||
|
|||
buff = NULL; |
|||
|
|||
/* locate the file on the CD */ |
|||
if( CdSearchFile( filename, &filePos ) == NULL ) |
|||
{ |
|||
/* print error message if file not found */ |
|||
printf( "%s not found.", filename ); |
|||
} |
|||
else |
|||
{ |
|||
/* calculate number of sectors to read for the file */ |
|||
numsecs = (filePos.size+2047)/2048; |
|||
|
|||
/* allocate buffer for the file (replace with malloc3() for PsyQ) */ |
|||
buff = (char*)malloc( 2048*numsecs ); |
|||
|
|||
/* set read target to the file */ |
|||
CdControl( CdlSetloc, (u_char*)&filePos.loc, 0 ); |
|||
|
|||
/* start read operation */ |
|||
CdRead( numsecs, (u_long*)buff, CdlModeSpeed ); |
|||
|
|||
/* wait until the read operation is complete */ |
|||
CdReadSync( 0, 0 ); |
|||
} |
|||
|
|||
return( buff ); |
|||
|
|||
} /* loadfile */ |
|||
</pre> |
|||
|
|||
<p>The sample program from the last chapter will be used to demonstrate the |
|||
usage of the function, to load the texture image from CD rather than loading |
|||
from an array. The ever growing sample program should be like this. Tweak |
|||
the code as you see fit to make it work with the SDK you're using.</p> |
|||
|
|||
<pre>#include <sys/types.h> // This provides typedefs needed by libgte.h and libgpu.h |
|||
#include <stdio.h> // Not necessary but include it anyway |
|||
#include <psxetc.h> // Includes some functions that controls the display |
|||
#include <psxgte.h> // GTE header, not really used but libgpu.h depends on it |
|||
#include <psxgpu.h> // GPU library header |
|||
#include <psxapi.h> |
|||
|
|||
#define OTLEN 8 // Ordering table length (recommended to set as a define |
|||
// so it can be changed easily) |
|||
|
|||
DISPENV disp[2]; // Display/drawing buffer parameters |
|||
DRAWENV draw[2]; |
|||
int db = 0; |
|||
|
|||
// PSn00bSDK requires having all u_long types replaced with |
|||
// u_int, as u_long in modern GCC that PSn00bSDK uses defines it as a 64-bit integer. |
|||
|
|||
u_int ot[2][OTLEN]; // Ordering table length |
|||
char pribuff[2][32768]; // Primitive buffer |
|||
char *nextpri; // Next primitive pointer |
|||
|
|||
int tim_mode; // TIM image parameters |
|||
RECT tim_prect,tim_crect; |
|||
int tim_uoffs,tim_voffs; |
|||
|
|||
// Pad stuff |
|||
#define PAD_SELECT 1 |
|||
#define PAD_L3 2 |
|||
#define PAD_R3 4 |
|||
#define PAD_START 8 |
|||
#define PAD_UP 16 |
|||
#define PAD_RIGHT 32 |
|||
#define PAD_DOWN 64 |
|||
#define PAD_LEFT 128 |
|||
#define PAD_L2 256 |
|||
#define PAD_R2 512 |
|||
#define PAD_L1 1024 |
|||
#define PAD_R1 2048 |
|||
#define PAD_TRIANGLE 4096 |
|||
#define PAD_CIRCLE 8192 |
|||
#define PAD_CROSS 16384 |
|||
#define PAD_SQUARE 32768 |
|||
|
|||
typedef struct _PADTYPE |
|||
{ |
|||
unsigned char stat; |
|||
unsigned char len:4; |
|||
unsigned char type:4; |
|||
unsigned short btn; |
|||
unsigned char rs_x,rs_y; |
|||
unsigned char ls_x,ls_y; |
|||
} PADTYPE; |
|||
|
|||
u_char padbuff[2][34]; |
|||
|
|||
// For the player triangle |
|||
SVECTOR player_tri[] = { |
|||
{ 0, -20, 0 }, |
|||
{ 10, 20, 0 }, |
|||
{ -10, 20, 0 } |
|||
}; |
|||
|
|||
void display() { |
|||
|
|||
DrawSync(0); // Wait for any graphics processing to finish |
|||
|
|||
VSync(0); // Wait for vertical retrace |
|||
|
|||
PutDispEnv(&disp[db]); // Apply the DISPENV/DRAWENVs |
|||
PutDrawEnv(&draw[db]); |
|||
|
|||
SetDispMask(1); // Enable the display |
|||
|
|||
DrawOTag(ot[db]+OTLEN-1); // Draw the ordering table |
|||
|
|||
db = !db; // Swap buffers on every pass (alternates between 1 and 0) |
|||
nextpri = pribuff[db]; // Reset next primitive pointer |
|||
|
|||
} |
|||
|
|||
// CD loading function |
|||
char *loadfile( const char *filename ) |
|||
{ |
|||
CdlFILE filePos; |
|||
int numsecs; |
|||
char *buff; |
|||
|
|||
buff = NULL; |
|||
|
|||
/* locate the file on the CD */ |
|||
if( CdSearchFile( filename, &filePos ) == NULL ) |
|||
{ |
|||
/* print error message if file not found */ |
|||
printf( "%s not found.", filename ); |
|||
} |
|||
else |
|||
{ |
|||
/* calculate number of sectors to read for the file */ |
|||
numsecs = (filePos.size+2047)/2048; |
|||
|
|||
/* allocate buffer for the file (replace with malloc3() for PsyQ) */ |
|||
buff = (char*)malloc( 2048*numsecs ); |
|||
|
|||
/* set read target to the file */ |
|||
CdControl( CdlSetloc, (u_char*)&filePos.loc, 0 ); |
|||
|
|||
/* start read operation */ |
|||
CdRead( numsecs, (u_long*)buff, CdlModeSpeed ); |
|||
|
|||
/* wait until the read operation is complete */ |
|||
CdReadSync( 0, 0 ); |
|||
} |
|||
|
|||
return( buff ); |
|||
|
|||
} /* loadfile */ |
|||
|
|||
// Texture upload function |
|||
void LoadTexture(u_int *tim, TIM_IMAGE *tparam) { |
|||
|
|||
// Read TIM parameters (PsyQ) |
|||
//OpenTIM(tim); |
|||
//ReadTIM(tparam); |
|||
|
|||
// Read TIM parameters (PSn00bSDK) |
|||
GetTimInfo(tim, tparam); |
|||
|
|||
// Upload pixel data to framebuffer |
|||
LoadImage(tparam->prect, tparam->paddr); |
|||
DrawSync(0); |
|||
|
|||
// Upload CLUT to framebuffer if present |
|||
if( tparam->mode & 0x8 ) { |
|||
|
|||
LoadImage(tparam->crect, tparam->caddr); |
|||
DrawSync(0); |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
void loadstuff(void) { |
|||
|
|||
TIM_IMAGE my_image; // TIM image parameters |
|||
u_int *filebuff; // Pointer for the file loaded from the disc |
|||
|
|||
if( filebuff = (u_int*)loadfile( "\\TEXTURE.TIM;1" ) ) |
|||
{ |
|||
// On successful file read, load the texture to VRAM |
|||
LoadTexture(tim_my_image, &my_image); |
|||
|
|||
// Copy the TIM coordinates |
|||
tim_prect = *my_image.prect; |
|||
tim_crect = *my_image.crect; |
|||
tim_mode = my_image.mode; |
|||
|
|||
// Calculate U,V offset for TIMs that are not page aligned |
|||
tim_uoffs = (tim_prect.x%64)<<(2-(tim_mode&0x3)); |
|||
tim_voffs = (tim_prect.y&0xff); |
|||
|
|||
// Free the file buffer |
|||
free( filebuff ); |
|||
} |
|||
else |
|||
{ |
|||
// Output error text that the image failed to load |
|||
printf( "Error: TEXTURE.TIM file not found.\n" ); |
|||
} |
|||
} |
|||
|
|||
// To make main look tidy, init stuff has to be moved here |
|||
void init(void) { |
|||
|
|||
// Reset graphics |
|||
ResetGraph(0); |
|||
|
|||
// Initialize the CD-ROM library |
|||
CdInit(); |
|||
|
|||
// First buffer |
|||
SetDefDispEnv(&disp[0], 0, 0, 320, 240); |
|||
SetDefDrawEnv(&draw[0], 0, 240, 320, 240); |
|||
// Second buffer |
|||
SetDefDispEnv(&disp[1], 0, 240, 320, 240); |
|||
SetDefDrawEnv(&draw[1], 0, 0, 320, 240); |
|||
|
|||
draw[0].isbg = 1; // Enable clear |
|||
setRGB0(&draw[0], 63, 0, 127); // Set clear color (dark purple) |
|||
draw[1].isbg = 1; |
|||
setRGB0(&draw[1], 63, 0, 127); |
|||
|
|||
nextpri = pribuff[0]; // Set initial primitive pointer address |
|||
|
|||
// load textures and possibly other stuff |
|||
loadstuff(); |
|||
|
|||
// set tpage of lone texture as initial tpage |
|||
draw[0].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
draw[1].tpage = getTPage( tim_mode&0x3, 0, tim_prect.x, tim_prect.y ); |
|||
|
|||
// apply initial drawing environment |
|||
PutDrawEnv(&draw[!db]); |
|||
|
|||
// Initialize the pads |
|||
InitPAD( padbuff[0], 34, padbuff[1], 34 ); |
|||
|
|||
// Begin polling |
|||
StartPAD(); |
|||
|
|||
// To avoid VSync Timeout error, may not be defined in PsyQ |
|||
ChangeClearPAD( 1 ); |
|||
|
|||
// Load the font texture on the upper-right corner of the VRAM |
|||
FntLoad( 960, 0 ); |
|||
|
|||
// Define a font window of 100 characters covering the whole screen |
|||
FntOpen( 0, 8, 320, 224, 0, 100 ); |
|||
|
|||
} |
|||
|
|||
int main() { |
|||
|
|||
int i; |
|||
int pos_x,pos_y,angle; |
|||
PADTYPE *pad; |
|||
POLY_F3 *tri; |
|||
SVECTOR v[3]; |
|||
|
|||
TILE *tile; // Pointer for TILE |
|||
SPRT *sprt; // Pointer for SPRT |
|||
|
|||
// Init stuff |
|||
init(); |
|||
|
|||
pos_x = ONE*(disp[0].disp.w>>1); |
|||
pos_y = ONE*(disp[0].disp.h>>1); |
|||
angle = 0; |
|||
|
|||
while(1) { |
|||
|
|||
// Parse controller input |
|||
pad = (PADTYPE*)padbuff[0]; |
|||
|
|||
// Only parse inputs when a controller is connected |
|||
if( pad->stat == 0 ) |
|||
{ |
|||
// Only parse when a digital pad, |
|||
// dual-analog and dual-shock is connected |
|||
if( ( pad->type == 0x4 ) || |
|||
( pad->type == 0x5 ) || |
|||
( pad->type == 0x7 ) ) |
|||
{ |
|||
if( !(pad->btn&PAD_UP) ) // test UP |
|||
{ |
|||
pos_x += csin( angle ); |
|||
pos_y -= ccos( angle ); |
|||
} |
|||
else if( !(pad->btn&PAD_DOWN) ) // test DOWN |
|||
{ |
|||
pos_x -= csin( angle ); |
|||
pos_y += ccos( angle ); |
|||
} |
|||
if( !(pad->btn&PAD_LEFT) ) // test LEFT |
|||
{ |
|||
angle -= 16; |
|||
} |
|||
else if( !(pad->btn&PAD_RIGHT) ) // test RIGHT |
|||
{ |
|||
angle += 16; |
|||
} |
|||
} |
|||
} |
|||
|
|||
ClearOTagR(ot[db], OTLEN); // Clear ordering table |
|||
|
|||
// Rotate the triangle coordinates based on the player's angle |
|||
// as well as apply the position |
|||
for( i=0; i<3; i++ ) |
|||
{ |
|||
v[i].vx = (((player_tri[i].vx*icos( angle )) |
|||
-(player_tri[i].vy*csin( angle )))>>12)+(pos_x>>12); |
|||
v[i].vy = (((player_tri[i].vy*icos( angle )) |
|||
+(player_tri[i].vx*csin( angle )))>>12)+(pos_y>>12); |
|||
} |
|||
|
|||
// Sort the player triangle |
|||
tri = (POLY_F3*)nextpri; |
|||
setPolyF3( tri ); |
|||
setRGB0( tri, 255, 255, 0 ); |
|||
setXY3( tri, |
|||
v[0].vx, v[0].vy, |
|||
v[1].vx, v[1].vy, |
|||
v[2].vx, v[2].vy ); |
|||
addPrim( ot[db], tri ); |
|||
nextpri += sizeof(POLY_F3); |
|||
|
|||
// Print player coordinates |
|||
FntPrint( -1, "POS_X=%d (%d.%d)\n", pos_x, (pos_x>>12), (pos_x&0xfff) ); |
|||
FntPrint( -1, "POS_Y=%d (%d.%d)\n", pos_y, (pos_y>>12), (pos_y&0xfff) ); |
|||
FntPrint( -1, "ANGLE=%d\n", angle ); |
|||
|
|||
// Draw and flush the character buffer |
|||
FntFlush( -1 ); |
|||
|
|||
// Update the display |
|||
display(); |
|||
|
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
|
|||
<h2 id="makecd">Creating the CD Image</h2> |
|||
|
|||
<p>Once you've got the code above compiled it won't do jack for now as it |
|||
doesn't yet have a CD to read the texture file from. This is where disc |
|||
image creation comes to play in this chapter.</p> |
|||
|
|||
<p>In the old days, the only preferred way to create PlayStation CD images |
|||
was with the old, MS-DOS based BUILDCD tool from the old leaked PsyQ SDK |
|||
dump. This tool is quite difficult to use on modern computers these days |
|||
largely due to being a 16-bit MS-DOS program, and while Dosbox can be used |
|||
to get it going on a modern machine it is not exactly ideal, not to mention |
|||
is very slow.</p> |
|||
|
|||
<p>To make image creation even more tedious with the old BUILDCD method |
|||
the resulting image file is of a special format intended for early CD |
|||
burners and special disc cutters, so another tool called STRIPISO is |
|||
used to convert the image file to that of a usable file format. However, |
|||
the conversion process does not convert the Table-of-Contents data |
|||
produced by BUILDCD as well, so having multiple tracks in the disc image |
|||
was not possible with this method.</p> |
|||
|
|||
<p>While other, more conventional means of disc image creation like |
|||
MKISOFS would work, it is not exactly ideal for projects that use XA |
|||
audio or streaming data which require support for mixed Mode2/Form1 |
|||
and Mode2/Form2 not supported by MKISOFS so you'd be stuck with having |
|||
to use BUILDCD in the old days. Well... That is until |
|||
<a href="https://github.com/lameguy64/mkpsxiso">MKPSXISO</a> by |
|||
yours truly came about, solving this disc image creation dilemma in the |
|||
PlayStation homebrew scene once and for all. Said tool was so useful that |
|||
it got used quite extensively around ROM hacking and game translation |
|||
groups... Or so I heard.</p> |
|||
|
|||
<h3>Creating a MKPSXISO Script</h3> |
|||
|
|||
<p>Kind of like BUILDCD, MKPSXISO uses a simple script system to define |
|||
the contents and layout of a CD image. However, it uses a XML based |
|||
format similar to that you'd find in HTML webpage files, of which, in |
|||
of itself is quite simple especially if you use a good text editor |
|||
such as Notepad++ or nedit.</p> |
|||
|
|||
<p>The following is a link to a sample XML script for this tutorial. |
|||
You must save the link as a file as otherwise your browser's going to |
|||
treat it as a web page. The file also contains comments that explains |
|||
the usage of the XML file.</p> |
|||
|
|||
<a href="http://lameguy64.net/tutorials/pstutorials/chapter1/mkpsxiso-sample.xml">MKPSXISO Sample Script</a> |
|||
|
|||
<p>The script file assumes that the above C program is compiled as |
|||
<b>cdread.exe</b>.</p> |
|||
|
|||
<h3>Creating the SYSTEM.CNF File</h3> |
|||
|
|||
<p>Before the ISO image can be created, a <b>SYSTEM.CNF</b> file must be |
|||
created and is a standard requirement for PlayStation game discs to include. |
|||
The <b>SYSTEM.CNF</b> file is a simple text file that defines a few |
|||
parameters. The most important being the <b>BOOT</b> variable.</p> |
|||
|
|||
<pre>BOOT=cdrom:\cdread.exe;1 |
|||
TCB=4 |
|||
EVENT=10 |
|||
STACK=801FFFF0 |
|||
</pre> |
|||
|
|||
<p>The parameters that immediately follow it <b>TCB</b>, <b>EVENT</b> and |
|||
<b>STACK</b> are special parameters that change the way how the kernel |
|||
is set up for the game. The parameters in the sample script are typical |
|||
values used in most games, so they can be left alone.</p> |
|||
|
|||
<p>Save the text file as <b>SYSTEM.TXT</b> as the script provided will |
|||
rename it as <b>SYSTEM.CNF</b> as the disc image gets created. This is |
|||
done so that editing the CNF file is made easier when need-be, such as |
|||
changing the executable name.</p> |
|||
|
|||
<h3>Creating the disc image</h3> |
|||
|
|||
<p>Building the disc image with MKPSXISO is just a matter of simply |
|||
invoking it from the command line with the XML script as the argument. |
|||
|
|||
</p><pre>mkpsxiso mkpsxiso-sample.xml |
|||
</pre> |
|||
|
|||
<p>If things go accordingly you should end up with a BIN/CUE image pair |
|||
named <b>cdtutorial</b>. Run the disc image in your preferred emulator |
|||
and the program from the last tutorial should work now, only there's now |
|||
a slight delay from loading data from the disc.</p> |
|||
|
|||
<center> |
|||
<img src="Chapter%201.6%20Using%20the%20CD-ROM_files/rotscalesprite.png"> |
|||
</center> |
|||
|
|||
<h2>Conclusion</h2> |
|||
|
|||
<p>Hopefully this chapter has cleared up a lot of things in regards to |
|||
reading data from the CD, something I feel is still not explained very |
|||
well. But then I haven't really kept up with the PlayStation homebrew |
|||
scene in a very long while. In the future, stuff like CD Audio and XA |
|||
audio playback will be covered.</p> |
|||
|
|||
<p>And this concludes the basics chapter of this tutorial series, and |
|||
if you've managed to reach this far after reading the first few chapters |
|||
you should be able to do quite a bit with 2D stuff on the console now... |
|||
Provided you managed to absorb it all.</p> |
|||
|
|||
<hr> |
|||
<table width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left"><a href="http://lameguy64.net/tutorials/pstutorials/chapter1/5-fixedpoint.html">Previous</a></td> |
|||
<td width="20%" align="center"><a href="http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
</body></html> |
|||
@ -0,0 +1,49 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
@ -0,0 +1,508 @@ |
|||
<html><head><script src="Chapter%202.2%20Reading%20a%20file%20from%20CD-ROM_files/analytics.js" type="text/javascript"></script> |
|||
<script type="text/javascript">window.addEventListener('DOMContentLoaded',function(){var v=archive_analytics.values;v.service='wb';v.server_name='wwwb-app226.us.archive.org';v.server_ms=523;archive_analytics.send_pageview({});});</script> |
|||
<script type="text/javascript" src="Chapter%202.2%20Reading%20a%20file%20from%20CD-ROM_files/bundle-playback.js" charset="utf-8"></script> |
|||
<script type="text/javascript" src="Chapter%202.2%20Reading%20a%20file%20from%20CD-ROM_files/wombat.js" charset="utf-8"></script> |
|||
<script type="text/javascript"> |
|||
__wm.init("http://web.archive.org/web"); |
|||
__wm.wombat("http://lameguy64.net/tutorials/pstutorials/chapter2-old/2-readfile.html","20220827033533","http://web.archive.org/","web","/_static/", |
|||
"1661571333"); |
|||
</script> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%202.2%20Reading%20a%20file%20from%20CD-ROM_files/banner-styles.css"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%202.2%20Reading%20a%20file%20from%20CD-ROM_files/iconochive.css"> |
|||
<!-- End Wayback Rewrite JS Include --> |
|||
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<link rel="stylesheet" type="text/css" href="Chapter%202.2%20Reading%20a%20file%20from%20CD-ROM_files/style.css"> |
|||
<title>Chapter 2.2: Reading a file from CD-ROM</title> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
|||
</head> |
|||
<body><!-- BEGIN WAYBACK TOOLBAR INSERT --> |
|||
<style type="text/css"> |
|||
body { |
|||
margin-top:0 !important; |
|||
padding-top:0 !important; |
|||
/*min-width:800px !important;*/ |
|||
} |
|||
</style> |
|||
<script>__wm.rw(0);</script> |
|||
<div id="wm-ipp-base" style="display: block; direction: ltr;" lang="en"> |
|||
</div><div id="wm-ipp-print">The Wayback Machine - |
|||
http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter2-old/2-readfile.html</div> |
|||
<script type="text/javascript">//<![CDATA[ |
|||
__wm.bt(675,27,25,2,"web","http://lameguy64.net/tutorials/pstutorials/chapter2-old/2-readfile.html","20220827033533",1996,"/_static/",["/_static/css/banner-styles.css?v=fantwOh2","/_static/css/iconochive.css?v=qtvMKcIJ"], false); |
|||
__wm.rw(1); |
|||
//]]></script> |
|||
<!-- END WAYBACK TOOLBAR INSERT --> |
|||
|
|||
<header> |
|||
<h1>Chapter 2.2: Reading a file from CD-ROM</h1> |
|||
</header> |
|||
<p>This chapter details how to read a file from the CD-ROM, loading the contents |
|||
into system RAM using the CD-ROM library.</p> |
|||
<p><b>PSn00bSDK Compatible:</b> Yes</p> |
|||
|
|||
<h2>Tutorial Index</h2> |
|||
<ul> |
|||
<li><a href="#cdinit">Initializing the CD-ROM</a></li> |
|||
<li><a href="#filelocate">Locating a file in the CD-ROM</a></li> |
|||
<li><a href="#reading">Reading File Contents</a></li> |
|||
<li><a href="#readfunc">Simple File Read Function</a></li> |
|||
<li><a href="#imagedemo">Image Loader Example</a></li> |
|||
<li><a href="#imagebuild">Building the ISO image</a></li> |
|||
<li><a href="#conclusion">Conclusion</a></li> |
|||
</ul> |
|||
|
|||
<h2 id="cdinit">Initializing the CD-ROM</h2> |
|||
<p>Initializing the CD-ROM library is accomplished by simply calling |
|||
<b>CdInit()</b>. This function must be called after calling <b>ResetGraph()</b> |
|||
and before any CD library related function. If you intend to use the SPU you |
|||
must call <b>SpuInit()</b> immediately before calling <b>CdInit()</b>. Once the |
|||
CD-ROM library is initialized any other CD-ROM related function can be used.</p> |
|||
<h3>SDK Difference</h3> |
|||
<p>In PsyQ/Programmers' Tool, <b>CdInit()</b> will throw a lot of CD retry |
|||
messages when no disc is inserted and may lock up. In PSn00bSDK the function |
|||
carries on like normal when no disc is inserted.</p> |
|||
|
|||
<h2 id="filelocate">Locating a file in the CD-ROM</h2> |
|||
<p>The CD-ROM library does not have a concept of file handles. Instead, files |
|||
are read by locating the start position of a file through the ISO9660 file |
|||
system, seeking to it and issuing a read operation until a set number of |
|||
sectors have been read. This method of loading files from disc should not be |
|||
a problem under any circumstances as files stored in a ISO9660 file system are |
|||
never fragmented. In fact, this method of reading files may have some |
|||
advantages.</p> |
|||
<p>Locating a file on the disc is done through the <b>CdSearchFile()</b> |
|||
function, which parses through the disc's file system to locate the file |
|||
and returns a <b>CdlFILE</b> which describes information about the file found |
|||
including it's position in the disc.</p> |
|||
<pre>CdlFILE file; |
|||
|
|||
// Search for the file |
|||
if( !CdSearchFile( &file;, "\\MYDIR\\MYFILE.DAT;1" ) ) |
|||
{ |
|||
// Return value is NULL, file is not found |
|||
printf( "File not found.\n" ); |
|||
return 0; |
|||
} |
|||
|
|||
// When file found |
|||
printf( "File found!\n" ); |
|||
</pre> |
|||
<p>The file name must be specified as a complete path from root and must use |
|||
backlash characters as directory separators (use \\ in C code). The file name |
|||
must also end with a file version number which is always ';1'. If the file is |
|||
found, it will return the pointer to the specified <b>CdlFILE</b> struct, |
|||
otherwise it would simply return NULL.</p> |
|||
<p>The <b>CdlFILE</b> struct contains a copy of the file name, file size and |
|||
most importantly, the location.</p> |
|||
|
|||
<h2 id="reading">Reading File Contents</h2> |
|||
<p>Now for the interesting stuff. Reading sectors is accomplished by using |
|||
<b>CdRead()</b>. But before you start a read operation, you must first set |
|||
the location of where to start reading from. This can be done using |
|||
<b>CdControl()</b> and the <b>CdlSetloc</b> command. Use this to set the |
|||
target location of the file.</p> |
|||
<pre>char *buffer; |
|||
|
|||
// Allocate a buffer for the file |
|||
buffer = (char*)malloc( 2048*((file.size+2047)/2048) ); |
|||
|
|||
// Set seek target (seek actually happens on CdRead()) |
|||
CdControl( CdSetloc, &file.loc;, 0 ); |
|||
|
|||
// Read sectors |
|||
CdRead( (file.size+2047)/2048, (unsigned int*)buffer, CdlModeSpeed ); |
|||
|
|||
// Wait until read has completed |
|||
CdReadSync( 0, 0 ); |
|||
</pre> |
|||
<p>You may have noticed by now that read sizes in this chapter are described in |
|||
sector units rather than byte units. That's because the CD-ROM subsystem can |
|||
only read in sector units and the CD-ROM library is optimized for reading in |
|||
sector units rather than buffering sectors to allow for byte by byte reading |
|||
for performance reasons.</p> |
|||
<p>Data sectors are typically 2048 bytes in size so buffers where data read |
|||
from the CD would be loaded to must be multiples of 2048 bytes. The arithmetic |
|||
to snap byte sizes to the nearest sector unit is described in the pseudo code |
|||
described above.</p> |
|||
<p>Once a read operation has been issued, you must wait until reading has |
|||
completed using <b>CdReadSync()</b>. You can alternatively poll the status |
|||
asynchronously by setting the <i>mode</i> parameter to 1 to perform animations |
|||
while waiting for a long read to complete.</p> |
|||
<p>If you intend to read only a part of a file instead of a whole file in a |
|||
single read operation, be aware that you can't simply call <b>CdRead()</b> |
|||
again to read the following sectors. Instead, you must retrieve the current |
|||
location using <b>CdlGetloc</b>, set it as the seek target with <b>CdlSetloc</b> |
|||
then call <b>CdRead()</b>.</p> |
|||
|
|||
|
|||
<h2 id="readfunc">Simple File Read Function</h2> |
|||
<p>The examples described above can be consolidated into a single function, |
|||
which can be useful for quickly implementing a file read function for testing |
|||
purposes:</p> |
|||
<pre>u_long *load_file(const char* filename) |
|||
{ |
|||
CdlFILE file; |
|||
u_long *buffer; |
|||
|
|||
|
|||
printf( "Reading file %s... ", filename ); |
|||
|
|||
// Search for the file |
|||
if( !CdSearchFile( &file;, (char*)filename ) ) |
|||
{ |
|||
// Return value is NULL, file is not found |
|||
printf( "Not found!\n" ); |
|||
return NULL; |
|||
} |
|||
|
|||
// Allocate a buffer for the file |
|||
buffer = (u_long*)malloc( 2048*((file.size+2047)/2048) ); |
|||
|
|||
// Set seek target (seek actually happens on CdRead()) |
|||
CdControl( CdlSetloc, (u_char*)&file.pos;, 0 ); |
|||
|
|||
// Read sectors |
|||
CdRead( (file.size+2047)/2048, buffer, CdlModeSpeed ); |
|||
|
|||
// Wait until read has completed |
|||
CdReadSync( 0, 0 ); |
|||
|
|||
printf( "Done.\n" ); |
|||
|
|||
return buffer; |
|||
} |
|||
</pre> |
|||
<p>If you want to do asynchronous loading to do background animations, you'll |
|||
have to use the CD functions more directly.</p> |
|||
|
|||
|
|||
<h2 id="imagedemo">Image Loader Example</h2> |
|||
<p>For completedness, this example demonstrates loading a high resolution |
|||
24-bit TIM from CD and displaying it into the framebuffer in 24-bit color mode. |
|||
Take any image file you wish to use, scale it down to 640x480 and convert it |
|||
into a 24-bit TIM with the load position set to (0,0). Name that TIM file |
|||
<i>myimage.tim</i> for this example.</p> |
|||
<p><b>PsyQ/Programmers' Tool Version</b></p> |
|||
<pre>#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <sys/types.h> |
|||
#include <libgte.h> |
|||
#include <libgpu.h> |
|||
#include <libetc.h> |
|||
#include <libcd.h> |
|||
|
|||
// Display environment struct |
|||
DISPENV disp; |
|||
|
|||
u_long *load_file(const char* filename) |
|||
{ |
|||
CdlFILE file; |
|||
u_long *buffer; |
|||
|
|||
|
|||
printf( "Reading file %s... ", filename ); |
|||
|
|||
// Search for the file |
|||
if( !CdSearchFile( &file;, (char*)filename ) ) |
|||
{ |
|||
// Return value is NULL, file is not found |
|||
printf( "Not found!\n" ); |
|||
return NULL; |
|||
} |
|||
|
|||
// Allocate a buffer for the file |
|||
buffer = (u_long*)malloc( 2048*((file.size+2047)/2048) ); |
|||
|
|||
// Set seek target (seek actually happens on CdRead()) |
|||
CdControl( CdlSetloc, (u_char*)&file.pos;, 0 ); |
|||
|
|||
// Read sectors |
|||
CdRead( (file.size+2047)/2048, buffer, CdlModeSpeed ); |
|||
|
|||
// Wait until read has completed |
|||
CdReadSync( 0, 0 ); |
|||
|
|||
printf( "Done.\n" ); |
|||
|
|||
return buffer; |
|||
} |
|||
|
|||
void display_picture() |
|||
{ |
|||
u_long *image; |
|||
TIM_IMAGE tim; |
|||
|
|||
// Load the image file |
|||
if( !(image = load_file( "\\MYIMAGE.TIM;1" )) ) |
|||
{ |
|||
printf( "Could not load image file.\n " ); |
|||
return; |
|||
} |
|||
|
|||
// Read TIM header |
|||
OpenTIM( image ); |
|||
ReadTIM( &tim; ); |
|||
|
|||
// Load image to VRAM |
|||
LoadImage( tim.prect, tim.paddr ); |
|||
DrawSync( 0 ); |
|||
|
|||
// Enable video display |
|||
VSync( 0 ); |
|||
SetDispMask( 1 ); |
|||
} |
|||
|
|||
void init() |
|||
{ |
|||
// Reset GPU (also installs IRQ handlers which are mandatory) |
|||
ResetGraph(0); |
|||
|
|||
// Init CD-ROM library |
|||
CdInit(); |
|||
|
|||
// Set DISPENV for 640x480 24-bit color mode |
|||
SetDefDispEnv( &disp;, 0, 0, 640, 480 ); |
|||
disp.isrgb24 = 1; // Enables 24-bit (cannot be used for GPU graphics) |
|||
disp.isinter = 1; // Enable interlace so hi-res will display properly |
|||
|
|||
// Set display environment |
|||
PutDispEnv( &disp; ); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) |
|||
{ |
|||
// Init stuff |
|||
init(); |
|||
|
|||
// Load and display picture |
|||
display_picture(); |
|||
|
|||
// Loop for safe idling |
|||
while( 1 ) |
|||
{ |
|||
VSync( 0 ); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
|
|||
<p><b>PSn00bSDK Version</b></p> |
|||
<pre>#include <stdio.h> |
|||
#include <malloc.h> |
|||
#include <psxgpu.h> |
|||
#include <psxcd.h> |
|||
|
|||
// Display environment struct |
|||
DISPENV disp; |
|||
|
|||
|
|||
unsigned int *load_file(const char* filename) |
|||
{ |
|||
CdlFILE file; |
|||
unsigned int *buffer; |
|||
|
|||
|
|||
printf( "Reading file %s... ", filename ); |
|||
|
|||
// Search for the file |
|||
if( !CdSearchFile( &file;, (char*)filename ) ) |
|||
{ |
|||
// Return value is NULL, file is not found |
|||
printf( "Not found!\n" ); |
|||
return NULL; |
|||
} |
|||
|
|||
// Allocate a buffer for the file |
|||
buffer = (unsigned int*)malloc( 2048*((file.size+2047)/2048) ); |
|||
|
|||
// Set seek target (seek actually happens on CdRead()) |
|||
CdControl( CdlSetloc, (unsigned char*)&file.pos;, 0 ); |
|||
|
|||
// Read sectors |
|||
CdRead( (file.size+2047)/2048, buffer, CdlModeSpeed ); |
|||
|
|||
// Wait until read has completed |
|||
CdReadSync( 0, 0 ); |
|||
|
|||
printf( "Done.\n" ); |
|||
|
|||
return buffer; |
|||
} |
|||
|
|||
void display_picture() |
|||
{ |
|||
unsigned int *image; |
|||
TIM_IMAGE tim; |
|||
|
|||
// Load the image file |
|||
if( !(image = load_file( "\\MYIMAGE.TIM;1" )) ) |
|||
{ |
|||
printf( "Could not load image file.\n " ); |
|||
return; |
|||
} |
|||
|
|||
// Read TIM header |
|||
GetTimInfo( image, &tim; ); |
|||
|
|||
// Load image to VRAM |
|||
LoadImage( tim.prect, tim.paddr ); |
|||
DrawSync( 0 ); |
|||
|
|||
// Enable video display |
|||
VSync( 0 ); |
|||
SetDispMask( 1 ); |
|||
} |
|||
|
|||
void init() |
|||
{ |
|||
// Reset GPU (also installs IRQ handlers which are mandatory) |
|||
ResetGraph(0); |
|||
|
|||
// Init CD-ROM library |
|||
CdInit( 0 ); |
|||
|
|||
// Set DISPENV for 640x480 24-bit color mode |
|||
SetDefDispEnv( &disp;, 0, 0, 640, 480 ); |
|||
disp.isrgb24 = 1; // Enables 24-bit (cannot be used for GPU graphics) |
|||
disp.isinter = 1; // Enable interlace so hi-res will display properly |
|||
|
|||
// Set display environment |
|||
PutDispEnv( &disp; ); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) |
|||
{ |
|||
// Init stuff |
|||
init(); |
|||
|
|||
// Load and display picture |
|||
display_picture(); |
|||
|
|||
// Loop for safe idling |
|||
while( 1 ) |
|||
{ |
|||
VSync( 0 ); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
</pre> |
|||
<p>Most notable differences between the PsyQ/Programmers' Tool and PSn00bSDK |
|||
versions is the latter uses type <b>unsigned int</b> instead of <b>u_long</b> |
|||
or <b>unsigned long</b> and for good reason. Modern compilers such as GCC |
|||
7.4.0 tend to assume long to be a 64-bit integer and may cause problems when |
|||
using <b>unsigned long</b>. There's no <b>OpenTIM()</b> and <b>ReadTIM()</b> |
|||
equivalent. Instead, there's <b>GetTimInfo()</b> but this may change in the |
|||
future.</p> |
|||
<p>Make sure you've compiled the example as readfile.exe for coherency with |
|||
the rest of this chapter.</p> |
|||
|
|||
<h2 id="imagebuild">Building the ISO image</h2> |
|||
<p>In the past, the only way to create proper ISO images for PS1 games is to |
|||
use a tool called BUILDCD included in leaked copies of the PsyQ SDK. The |
|||
biggest problem of using BUILDCD is it generates an image file of a special |
|||
format not supported by any burner program, so another tool has to be used |
|||
(stripiso) to convert the image file it generates into a usable ISO image. |
|||
Not only that, BUILDCD is a 16-bit DOS executable and is difficult and very |
|||
slow to use on a modern system.</p> |
|||
<p>Instead of using BUILDCD, use |
|||
<a href="http://web.archive.org/web/20220827033533/https://github.com/lameguy64/mkpsxiso">MKPSXISO</a> instead. It |
|||
offers about the same functionality as BUILDCD but better, and is built for |
|||
modern Windows and Linux platforms.</p> |
|||
<p><b>MKPSXISO Project XML</b></p> |
|||
<pre><?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<!-- Defines the ISO project --> |
|||
<iso_project image_name="readfile.iso"> |
|||
|
|||
<!-- Defines the data track for this tutorial --> |
|||
<track type="data"> |
|||
|
|||
<!-- Specifies identifier strings such as volume label --> |
|||
<!-- System and application identifiers must be PLAYSTATION --> |
|||
<identifiers |
|||
system ="PLAYSTATION" |
|||
application ="PLAYSTATION" |
|||
volume ="PSXTUTORIAL" |
|||
volume_set ="PSXTUTORIAL" |
|||
publisher ="MEIDOTEK" |
|||
/> |
|||
|
|||
<!-- Defines the directory tree of the data track --> |
|||
<directory_tree> |
|||
|
|||
<!-- Specify files in the directory tree --> |
|||
<file name="system.cnf" type="data" source="system.cnf"/> |
|||
<file name="readfile.exe" type="data" source="readfile.exe"/> |
|||
<file name="myimage.tim" type="data" source="myimage.tim"/> |
|||
|
|||
<!-- Place dummy sectors at the end --> |
|||
<dummy sectors="1024"/> |
|||
|
|||
</directory_tree> |
|||
|
|||
</track> |
|||
|
|||
</iso_project> |
|||
</pre> |
|||
<p>While on the subject of ISO image creation, you'll also need to create a |
|||
special SYSTEM.CNF file in order to make your disc image bootable. A |
|||
SYSTEM.CNF file is simply a text file that specifies the file name of the |
|||
executable, stack address, number of task and event blocks. The latter three |
|||
wouldn't be discussed in this chapter and the typical values are generally |
|||
good enough.</p> |
|||
<p><b>SYSTEM.CNF Contents</b></p> |
|||
<pre>BOOT=cdrom:\readfile.exe;1 |
|||
TCB=4 |
|||
EVENT=10 |
|||
STACK=801FFFF0 |
|||
</pre> |
|||
<p>Once your MKPSXISO project and SYSTEM.CNF files are set, execute MKPSXISO |
|||
like so to create the ISO image:</p> |
|||
<pre>mkpsxiso readfile.xml |
|||
</pre> |
|||
<p>Run the ISO image in an emulator and you should see your 24-bit TIM image |
|||
displayed. It may take awhile for the image to appear as the 24-bit TIM image |
|||
is a pretty big file to load for the PS1.</p> |
|||
<p></p> |
|||
|
|||
<h2 id="conclusion">Conclusion</h2> |
|||
<p>This chapter should cover about everything you need to know to load a file |
|||
from CD-ROM. The next chapter will cover common ways to optimize CD-ROM |
|||
accesses to speed up load times in your homebrew.</p> |
|||
|
|||
<hr> |
|||
<table class="footer-table" width="100%"> |
|||
<tbody><tr> |
|||
<td width="40%" align="left"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter2-old/1-cdrom.html">Previous</a></td> |
|||
<td width="20%" align="center"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/index.html">Back to Index</a></td> |
|||
<td width="40%" align="right"><a href="http://web.archive.org/web/20220827033533/http://lameguy64.net/tutorials/pstutorials/chapter2-old/3-optimizing.html">Next</a></td> |
|||
</tr> |
|||
</tbody></table> |
|||
|
|||
|
|||
|
|||
</body></html> |
|||
<!-- |
|||
FILE ARCHIVED ON 03:35:33 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:40:55 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
--> |
|||
<!-- |
|||
playback timings (ms): |
|||
captures_list: 170.071 |
|||
exclusion.robots: 0.17 |
|||
exclusion.robots.policy: 0.163 |
|||
RedisCDXSource: 0.884 |
|||
esindex: 0.008 |
|||
LoadShardBlock: 151.904 (3) |
|||
PetaboxLoader3.datanode: 200.102 (4) |
|||
CDXLines.iter: 14.739 (3) |
|||
load_resource: 348.367 |
|||
PetaboxLoader3.resolve: 286.145 |
|||
--> |
|||
@ -0,0 +1,474 @@ |
|||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3.0
|
|||
/* eslint-disable no-var, semi, prefer-arrow-callback, prefer-template */ |
|||
|
|||
/** |
|||
* Collection of methods for sending analytics events to Archive.org's analytics server. |
|||
* |
|||
* These events are used for internal stats and sent (in anonymized form) to Google Analytics. |
|||
* |
|||
* @see analytics.md |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
window.archive_analytics = (function defineArchiveAnalytics() { |
|||
// keep orignal Date object so as not to be affected by wayback's
|
|||
// hijacking global Date object
|
|||
var Date = window.Date; |
|||
var ARCHIVE_ANALYTICS_VERSION = 2; |
|||
var DEFAULT_SERVICE = 'ao_2'; |
|||
var NO_SAMPLING_SERVICE = 'ao_no_sampling'; // sends every event instead of a percentage
|
|||
|
|||
var startTime = new Date(); |
|||
|
|||
/** |
|||
* @return {Boolean} |
|||
*/ |
|||
function isPerformanceTimingApiSupported() { |
|||
return 'performance' in window && 'timing' in window.performance; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the browser starting to parse the DOM and |
|||
* the current time. |
|||
* |
|||
* Uses the Performance API or a fallback value if it's not available. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number} |
|||
*/ |
|||
function getLoadTime() { |
|||
var start; |
|||
|
|||
if (isPerformanceTimingApiSupported()) |
|||
start = window.performance.timing.domLoading; |
|||
else |
|||
start = startTime.getTime(); |
|||
|
|||
return new Date().getTime() - start; |
|||
} |
|||
|
|||
/** |
|||
* Determines how many milliseconds elapsed between the user navigating to the page and |
|||
* the current time. |
|||
* |
|||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Performance_API
|
|||
* |
|||
* @return {Number|null} null if the browser doesn't support the Performance API |
|||
*/ |
|||
function getNavToDoneTime() { |
|||
if (!isPerformanceTimingApiSupported()) |
|||
return null; |
|||
|
|||
return new Date().getTime() - window.performance.timing.navigationStart; |
|||
} |
|||
|
|||
/** |
|||
* Performs an arithmetic calculation on a string with a number and unit, while maintaining |
|||
* the unit. |
|||
* |
|||
* @param {String} original value to modify, with a unit |
|||
* @param {Function} doOperation accepts one Number parameter, returns a Number |
|||
* @returns {String} |
|||
*/ |
|||
function computeWithUnit(original, doOperation) { |
|||
var number = parseFloat(original, 10); |
|||
var unit = original.replace(/(\d*\.\d+)|\d+/, ''); |
|||
|
|||
return doOperation(number) + unit; |
|||
} |
|||
|
|||
/** |
|||
* Computes the default font size of the browser. |
|||
* |
|||
* @returns {String|null} computed font-size with units (typically pixels), null if it cannot be computed |
|||
*/ |
|||
function getDefaultFontSize() { |
|||
var fontSizeStr; |
|||
|
|||
if (!('getComputedStyle' in window)) |
|||
return null; |
|||
|
|||
var style = window.getComputedStyle(document.documentElement); |
|||
if (!style) |
|||
return null; |
|||
|
|||
fontSizeStr = style.fontSize; |
|||
|
|||
// Don't modify the value if tracking book reader.
|
|||
if (document.querySelector('#BookReader')) |
|||
return fontSizeStr; |
|||
|
|||
return computeWithUnit(fontSizeStr, function reverseBootstrapFontSize(number) { |
|||
// Undo the 62.5% size applied in the Bootstrap CSS.
|
|||
return number * 1.6; |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Get the URL parameters for a given Location |
|||
* @param {Location} |
|||
* @return {Object} The URL parameters |
|||
*/ |
|||
function getParams(location) { |
|||
if (!location) location = window.location; |
|||
var vars; |
|||
var i; |
|||
var pair; |
|||
var params = {}; |
|||
var query = location.search; |
|||
if (!query) return params; |
|||
vars = query.substring(1).split('&'); |
|||
for (i = 0; i < vars.length; i++) { |
|||
pair = vars[i].split('='); |
|||
params[pair[0]] = decodeURIComponent(pair[1]); |
|||
} |
|||
return params; |
|||
} |
|||
|
|||
function getMetaProp(name) { |
|||
var metaTag = document.querySelector('meta[property=' + name + ']'); |
|||
return metaTag ? metaTag.getAttribute('content') || null : null; |
|||
} |
|||
|
|||
var ArchiveAnalytics = { |
|||
/** |
|||
* @type {String|null} |
|||
*/ |
|||
service: getMetaProp('service'), |
|||
mediaType: getMetaProp('mediatype'), |
|||
primaryCollection: getMetaProp('primary_collection'), |
|||
|
|||
/** |
|||
* Key-value pairs to send in pageviews (you can read this after a pageview to see what was |
|||
* sent). |
|||
* |
|||
* @type {Object} |
|||
*/ |
|||
values: {}, |
|||
|
|||
/** |
|||
* Sends an analytics ping, preferably using navigator.sendBeacon() |
|||
* @param {Object} values |
|||
* @param {Function} [onload_callback] (deprecated) callback to invoke once ping to analytics server is done |
|||
* @param {Boolean} [augment_for_ao_site] (deprecated) if true, add some archive.org site-specific values |
|||
*/ |
|||
send_ping: function send_ping(values, onload_callback, augment_for_ao_site) { |
|||
if (typeof window.navigator !== 'undefined' && typeof window.navigator.sendBeacon !== 'undefined') |
|||
this.send_ping_via_beacon(values); |
|||
else |
|||
this.send_ping_via_image(values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Beacon API |
|||
* NOTE: Assumes window.navigator.sendBeacon exists |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_beacon: function send_ping_via_beacon(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
window.navigator.sendBeacon(url); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a ping via Image object |
|||
* @param {Object} values Tracking parameters to pass |
|||
*/ |
|||
send_ping_via_image: function send_ping_via_image(values) { |
|||
var url = this.generate_tracking_url(values || {}); |
|||
var loadtime_img = new Image(1, 1); |
|||
loadtime_img.src = url; |
|||
loadtime_img.alt = ''; |
|||
}, |
|||
|
|||
/** |
|||
* Construct complete tracking URL containing payload |
|||
* @param {Object} params Tracking parameters to pass |
|||
* @return {String} URL to use for tracking call |
|||
*/ |
|||
generate_tracking_url: function generate_tracking_url(params) { |
|||
var baseUrl = '//analytics.archive.org/0.gif'; |
|||
var keys; |
|||
var outputParams = params; |
|||
var outputParamsArray = []; |
|||
|
|||
outputParams.service = outputParams.service || this.service || DEFAULT_SERVICE; |
|||
|
|||
// Build array of querystring parameters
|
|||
keys = Object.keys(outputParams); |
|||
keys.forEach(function keyIteration(key) { |
|||
outputParamsArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(outputParams[key])); |
|||
}); |
|||
outputParamsArray.push('version=' + ARCHIVE_ANALYTICS_VERSION); |
|||
outputParamsArray.push('count=' + (keys.length + 2)); // Include `version` and `count` in count
|
|||
|
|||
return baseUrl + '?' + outputParamsArray.join('&'); |
|||
}, |
|||
|
|||
/** |
|||
* @param {int} page Page number |
|||
*/ |
|||
send_scroll_fetch_event: function send_scroll_fetch_event(page) { |
|||
var additionalValues = { ev: page }; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
send_scroll_fetch_base_event: function send_scroll_fetch_base_event() { |
|||
var additionalValues = {}; |
|||
var loadTime = getLoadTime(); |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
if (loadTime) additionalValues.loadtime = loadTime; |
|||
if (navToDoneTime) additionalValues.nav_to_done_ms = navToDoneTime; |
|||
this.send_event('page_action', 'scroll_fetch_base', location.pathname, additionalValues); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} [options] |
|||
* @param {String} [options.mediaType] |
|||
* @param {String} [options.mediaLanguage] |
|||
* @param {String} [options.page] The path portion of the page URL |
|||
*/ |
|||
send_pageview: function send_pageview(options) { |
|||
var settings = options || {}; |
|||
|
|||
var defaultFontSize; |
|||
var loadTime = getLoadTime(); |
|||
var mediaType = settings.mediaType; |
|||
var primaryCollection = settings.primaryCollection; |
|||
var page = settings.page; |
|||
var navToDoneTime = getNavToDoneTime(); |
|||
|
|||
/** |
|||
* @return {String} |
|||
*/ |
|||
function get_locale() { |
|||
if (navigator) { |
|||
if (navigator.language) |
|||
return navigator.language; |
|||
|
|||
else if (navigator.browserLanguage) |
|||
return navigator.browserLanguage; |
|||
|
|||
else if (navigator.systemLanguage) |
|||
return navigator.systemLanguage; |
|||
|
|||
else if (navigator.userLanguage) |
|||
return navigator.userLanguage; |
|||
} |
|||
return ''; |
|||
} |
|||
|
|||
defaultFontSize = getDefaultFontSize(); |
|||
|
|||
// Set field values
|
|||
this.values.kind = 'pageview'; |
|||
this.values.timediff = (new Date().getTimezoneOffset()/60)*(-1); // *timezone* diff from UTC
|
|||
this.values.locale = get_locale(); |
|||
this.values.referrer = (document.referrer == '' ? '-' : document.referrer); |
|||
|
|||
if (loadTime) |
|||
this.values.loadtime = loadTime; |
|||
|
|||
if (navToDoneTime) |
|||
this.values.nav_to_done_ms = navToDoneTime; |
|||
|
|||
if (settings.trackingId) { |
|||
this.values.ga_tid = settings.trackingId; |
|||
} |
|||
|
|||
/* START CUSTOM DIMENSIONS */ |
|||
if (defaultFontSize) |
|||
this.values.ga_cd1 = defaultFontSize; |
|||
|
|||
if ('devicePixelRatio' in window) |
|||
this.values.ga_cd2 = window.devicePixelRatio; |
|||
|
|||
if (mediaType) |
|||
this.values.ga_cd3 = mediaType; |
|||
|
|||
if (settings.mediaLanguage) { |
|||
this.values.ga_cd4 = settings.mediaLanguage; |
|||
} |
|||
|
|||
if (primaryCollection) { |
|||
this.values.ga_cd5 = primaryCollection; |
|||
} |
|||
/* END CUSTOM DIMENSIONS */ |
|||
|
|||
if (page) |
|||
this.values.page = page; |
|||
|
|||
this.send_ping(this.values); |
|||
}, |
|||
|
|||
/** |
|||
* Sends a tracking "Event". |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event: function send_event( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
if (!label) label = window.location.pathname; |
|||
if (!additionalEventParams) additionalEventParams = {}; |
|||
if (additionalEventParams.mediaLanguage) { |
|||
additionalEventParams.ga_cd4 = additionalEventParams.mediaLanguage; |
|||
delete additionalEventParams.mediaLanguage; |
|||
} |
|||
var eventParams = Object.assign( |
|||
{ |
|||
kind: 'event', |
|||
ec: category, |
|||
ea: action, |
|||
el: label, |
|||
cache_bust: Math.random(), |
|||
}, |
|||
additionalEventParams |
|||
); |
|||
this.send_ping(eventParams); |
|||
}, |
|||
|
|||
/** |
|||
* Sends every event instead of a small percentage. |
|||
* |
|||
* Use this sparingly as it can generate a lot of events. |
|||
* |
|||
* @param {string} category |
|||
* @param {string} action |
|||
* @param {string} label |
|||
* @param {Object} additionalEventParams |
|||
*/ |
|||
send_event_no_sampling: function send_event_no_sampling( |
|||
category, |
|||
action, |
|||
label, |
|||
additionalEventParams |
|||
) { |
|||
var extraParams = additionalEventParams || {}; |
|||
extraParams.service = NO_SAMPLING_SERVICE; |
|||
this.send_event(category, action, label, extraParams); |
|||
}, |
|||
|
|||
/** |
|||
* @param {Object} options see this.send_pageview options |
|||
*/ |
|||
send_pageview_on_load: function send_pageview_on_load(options) { |
|||
var self = this; |
|||
window.addEventListener('load', function send_pageview_with_options() { |
|||
self.send_pageview(options); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* Handles tracking events passed in URL. |
|||
* Assumes category and action values are separated by a "|" character. |
|||
* NOTE: Uses the unsampled analytics property. Watch out for future high click links! |
|||
* @param {Location} |
|||
*/ |
|||
process_url_events: function process_url_events(location) { |
|||
var eventValues; |
|||
var actionValue; |
|||
var eventValue = getParams(location).iax; |
|||
if (!eventValue) return; |
|||
eventValues = eventValue.split('|'); |
|||
actionValue = eventValues.length >= 1 ? eventValues[1] : ''; |
|||
this.send_event_no_sampling( |
|||
eventValues[0], |
|||
actionValue, |
|||
window.location.pathname |
|||
); |
|||
}, |
|||
|
|||
/** |
|||
* Attaches handlers for event tracking. |
|||
* |
|||
* To enable click tracking for a link, add a `data-event-click-tracking` |
|||
* attribute containing the Google Analytics Event Category and Action, separated |
|||
* by a vertical pipe (|). |
|||
* e.g. `<a href="foobar" data-event-click-tracking="TopNav|FooBar">` |
|||
* |
|||
* To enable form submit tracking, add a `data-event-form-tracking` attribute |
|||
* to the `form` tag. |
|||
* e.g. `<form data-event-form-tracking="TopNav|SearchForm" method="GET">` |
|||
* |
|||
* Additional tracking options can be added via a `data-event-tracking-options` |
|||
* parameter. This parameter, if included, should be a JSON string of the parameters. |
|||
* Valid parameters are: |
|||
* - service {string}: Corresponds to the Google Analytics property data values flow into |
|||
*/ |
|||
set_up_event_tracking: function set_up_event_tracking() { |
|||
var self = this; |
|||
var clickTrackingAttributeName = 'event-click-tracking'; |
|||
var formTrackingAttributeName = 'event-form-tracking'; |
|||
var trackingOptionsAttributeName = 'event-tracking-options'; |
|||
|
|||
function handleAction(event, attributeName) { |
|||
var selector = '[data-' + attributeName + ']'; |
|||
var eventTarget = event.target; |
|||
if (!eventTarget) return; |
|||
var target = eventTarget.closest(selector); |
|||
if (!target) return; |
|||
var categoryAction; |
|||
var categoryActionParts; |
|||
var options; |
|||
categoryAction = target.dataset[toCamelCase(attributeName)]; |
|||
if (!categoryAction) return; |
|||
categoryActionParts = categoryAction.split('|'); |
|||
options = target.dataset[toCamelCase(trackingOptionsAttributeName)]; |
|||
options = options ? JSON.parse(options) : {}; |
|||
self.send_event( |
|||
categoryActionParts[0], |
|||
categoryActionParts[1], |
|||
categoryActionParts[2] || window.location.pathname, |
|||
options.service ? { service: options.service } : {} |
|||
); |
|||
} |
|||
|
|||
function toCamelCase(str) { |
|||
return str.replace(/\W+(.)/g, function (match, chr) { |
|||
return chr.toUpperCase(); |
|||
}); |
|||
}; |
|||
|
|||
document.addEventListener('click', function(e) { |
|||
handleAction(e, clickTrackingAttributeName); |
|||
}); |
|||
|
|||
document.addEventListener('submit', function(e) { |
|||
handleAction(e, formTrackingAttributeName); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* @returns {Object[]} |
|||
*/ |
|||
get_data_packets: function get_data_packets() { |
|||
return [this.values]; |
|||
}, |
|||
|
|||
/** |
|||
* Creates a tracking image for tracking JS compatibility. |
|||
* |
|||
* @param {string} type The type value for track_js_case in query params for 0.gif |
|||
*/ |
|||
create_tracking_image: function create_tracking_image(type) { |
|||
this.send_ping_via_image({ |
|||
cache_bust: Math.random(), |
|||
kind: 'track_js', |
|||
track_js_case: type, |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
return ArchiveAnalytics; |
|||
}()); |
|||
// @license-end
|
|||
@ -0,0 +1,500 @@ |
|||
@import 'record.css'; /* for SPN1 */ |
|||
|
|||
#wm-ipp-base { |
|||
height:65px;/* initial height just in case js code fails */ |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
background:none transparent; |
|||
} |
|||
#wm-ipp { |
|||
z-index: 2147483647; |
|||
} |
|||
#wm-ipp, #wm-ipp * { |
|||
font-family:Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size:12px; |
|||
line-height:1.2; |
|||
letter-spacing:0; |
|||
width:auto; |
|||
height:auto; |
|||
max-width:none; |
|||
max-height:none; |
|||
min-width:0 !important; |
|||
min-height:0; |
|||
outline:none; |
|||
float:none; |
|||
text-align:left; |
|||
border:none; |
|||
color: #000; |
|||
text-indent: 0; |
|||
position: initial; |
|||
background: none; |
|||
} |
|||
#wm-ipp div, #wm-ipp canvas { |
|||
display: block; |
|||
} |
|||
#wm-ipp div, #wm-ipp tr, #wm-ipp td, #wm-ipp a, #wm-ipp form { |
|||
padding:0; |
|||
margin:0; |
|||
border:none; |
|||
border-radius:0; |
|||
background-color:transparent; |
|||
background-image:none; |
|||
/*z-index:2147483640;*/ |
|||
height:auto; |
|||
} |
|||
#wm-ipp table { |
|||
border:none; |
|||
border-collapse:collapse; |
|||
margin:0; |
|||
padding:0; |
|||
width:auto; |
|||
font-size:inherit; |
|||
} |
|||
#wm-ipp form input { |
|||
padding:1px !important; |
|||
height:auto; |
|||
display:inline; |
|||
margin:0; |
|||
color: #000; |
|||
background: none #fff; |
|||
border: 1px solid #666; |
|||
} |
|||
#wm-ipp form input[type=submit] { |
|||
padding:0 8px !important; |
|||
margin:1px 0 1px 5px !important; |
|||
width:auto !important; |
|||
border: 1px solid #000 !important; |
|||
background: #fff !important; |
|||
color: #000 !important; |
|||
} |
|||
#wm-ipp a { |
|||
display: inline; |
|||
} |
|||
#wm-ipp a:hover{ |
|||
text-decoration:underline; |
|||
} |
|||
#wm-ipp a.wm-btn:hover { |
|||
text-decoration:none; |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp a.wm-btn:hover span { |
|||
color:#ff0 !important; |
|||
} |
|||
#wm-ipp #wm-ipp-inside { |
|||
margin: 0 6px; |
|||
border:5px solid #000; |
|||
border-top:none; |
|||
background-color:rgba(255,255,255,0.9); |
|||
-moz-box-shadow:1px 1px 4px #333; |
|||
-webkit-box-shadow:1px 1px 4px #333; |
|||
box-shadow:1px 1px 4px #333; |
|||
border-radius:0 0 8px 8px; |
|||
} |
|||
/* selectors are intentionally verbose to ensure priority */ |
|||
#wm-ipp #wm-logo { |
|||
padding:0 10px; |
|||
vertical-align:middle; |
|||
min-width:100px; |
|||
flex: 0 0 100px; |
|||
} |
|||
#wm-ipp .c { |
|||
padding-left: 4px; |
|||
} |
|||
#wm-ipp .c .u { |
|||
margin-top: 4px !important; |
|||
} |
|||
#wm-ipp .n { |
|||
padding:0 0 0 5px !important; |
|||
vertical-align: bottom; |
|||
} |
|||
#wm-ipp .n a { |
|||
text-decoration:none; |
|||
color:#33f; |
|||
font-weight:bold; |
|||
} |
|||
#wm-ipp .n .b { |
|||
padding:0 6px 0 0 !important; |
|||
text-align:right !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n .y .b { |
|||
padding:0 6px 2px 0 !important; |
|||
} |
|||
#wm-ipp .n .c { |
|||
background:#000; |
|||
color:#ff0; |
|||
font-weight:bold; |
|||
padding:0 !important; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp.hi .n td.c { |
|||
color:#ec008c; |
|||
} |
|||
#wm-ipp .n td.f { |
|||
padding:0 0 0 6px !important; |
|||
text-align:left !important; |
|||
overflow:visible; |
|||
white-space:nowrap; |
|||
color:#99a; |
|||
vertical-align:middle; |
|||
} |
|||
#wm-ipp .n tr.m td { |
|||
text-transform:uppercase; |
|||
white-space:nowrap; |
|||
padding:2px 0; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 0 0 !important; |
|||
vertical-align:bottom; |
|||
} |
|||
#wm-ipp #wm-nav-captures { |
|||
white-space: nowrap; |
|||
} |
|||
#wm-ipp .c .s a.t { |
|||
color:#33f; |
|||
font-weight:bold; |
|||
line-height: 1.8; |
|||
} |
|||
#wm-ipp .c .s div.r { |
|||
color: #666; |
|||
font-size:9px; |
|||
white-space:nowrap; |
|||
} |
|||
#wm-ipp .c .k { |
|||
padding-bottom:1px; |
|||
} |
|||
#wm-ipp .c .s { |
|||
padding:0 5px 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayMonthEl { |
|||
padding: 2px 0 !important; |
|||
} |
|||
#wm-ipp td#displayYearEl { |
|||
padding: 0 0 2px 0 !important; |
|||
} |
|||
|
|||
div#wm-ipp-sparkline { |
|||
position:relative;/* for positioning markers */ |
|||
white-space:nowrap; |
|||
background-color:#fff; |
|||
cursor:pointer; |
|||
line-height:0.9; |
|||
} |
|||
#sparklineImgId, #wm-sparkline-canvas { |
|||
position:relative; |
|||
z-index:9012; |
|||
max-width:none; |
|||
} |
|||
#wm-ipp-sparkline div.yt { |
|||
position:absolute; |
|||
z-index:9010 !important; |
|||
background-color:#ff0 !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp-sparkline div.mt { |
|||
position:absolute; |
|||
z-index:9013 !important; |
|||
background-color:#ec008c !important; |
|||
top: 0; |
|||
} |
|||
#wm-ipp .r { |
|||
margin-left: 4px; |
|||
} |
|||
#wm-ipp .r a { |
|||
color:#33f; |
|||
border:none; |
|||
position:relative; |
|||
background-color:transparent; |
|||
background-repeat:no-repeat !important; |
|||
background-position:100% 100% !important; |
|||
text-decoration: none; |
|||
} |
|||
#wm-ipp #wm-capinfo { |
|||
/* prevents notice div background from sticking into round corners of |
|||
#wm-ipp-inside */ |
|||
border-radius: 0 0 4px 4px; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo { |
|||
display:block; |
|||
float:left; |
|||
margin-right:3px; |
|||
width:90px; |
|||
min-height:90px; |
|||
max-height: 290px; |
|||
border-radius:45px; |
|||
overflow:hidden; |
|||
background-position:50%; |
|||
background-size:auto 90px; |
|||
box-shadow: 0 0 2px 2px rgba(208,208,208,128) inset; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo span { |
|||
display:inline-block; |
|||
} |
|||
#wm-ipp #wm-capinfo .c-logo img { |
|||
height:90px; |
|||
position:relative; |
|||
left:-50%; |
|||
} |
|||
#wm-ipp #wm-capinfo .wm-title { |
|||
font-size:130%; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector { |
|||
display:inline-block; |
|||
color: #aaa; |
|||
text-decoration:none !important; |
|||
padding: 2px 8px; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector.selected { |
|||
background-color:#666; |
|||
} |
|||
#wm-ipp #wm-capinfo a.wm-selector:hover { |
|||
color: #fff; |
|||
} |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-collected-by, |
|||
#wm-ipp #wm-capinfo.notice-only #wm-capinfo-timestamps { |
|||
display: none; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content { |
|||
background-color:#ff0; |
|||
padding:5px; |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-capinfo #wm-capinfo-notice .wm-capinfo-content * { |
|||
font-size:14px; |
|||
text-align:center; |
|||
} |
|||
#wm-ipp #wm-expand { |
|||
right: 1px; |
|||
bottom: -1px; |
|||
color: #ffffff; |
|||
background-color: #666 !important; |
|||
padding:0 5px 0 3px !important; |
|||
border-radius: 3px 3px 0 0 !important; |
|||
} |
|||
#wm-ipp #wm-expand span { |
|||
color: #ffffff; |
|||
} |
|||
#wm-ipp #wm-expand #wm-expand-icon { |
|||
display: inline-block; |
|||
transition: transform 0.5s; |
|||
transform-origin: 50% 45%; |
|||
} |
|||
#wm-ipp #wm-expand.wm-open #wm-expand-icon { |
|||
transform: rotate(180deg); |
|||
} |
|||
#wm-ipp #wmtb { |
|||
text-align:right; |
|||
} |
|||
#wm-ipp #wmtb #wmtbURL { |
|||
width: calc(100% - 45px); |
|||
} |
|||
#wm-ipp #wm-graph-anchor { |
|||
border-right:1px solid #ccc; |
|||
} |
|||
/* time coherence */ |
|||
html.wb-highlight { |
|||
box-shadow: inset 0 0 0 3px #a50e3a !important; |
|||
} |
|||
.wb-highlight { |
|||
outline: 3px solid #a50e3a !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:none !important; |
|||
} |
|||
@media print { |
|||
#wm-ipp-base { |
|||
display:none !important; |
|||
} |
|||
#wm-ipp-print { |
|||
display:block !important; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
} |
|||
@media (max-width:414px) { |
|||
#wm-ipp .xxs { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (min-width:1055px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:block !important; |
|||
} |
|||
} |
|||
@media (max-width:1054px) { |
|||
#wm-ipp #wm-graph-anchor { |
|||
display:none !important; |
|||
} |
|||
} |
|||
@media (max-width:1163px) { |
|||
#wm-logo { |
|||
display:none !important; |
|||
} |
|||
} |
|||
|
|||
#wm-btns { |
|||
white-space: nowrap; |
|||
margin-top: -2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-open { |
|||
margin-right: 7px; |
|||
top: -6px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in { |
|||
box-sizing: content-box; |
|||
display: none; |
|||
margin-right: 7px; |
|||
top: -8px; |
|||
|
|||
/* |
|||
round border around sign in button |
|||
*/ |
|||
border: 2px #000 solid; |
|||
border-radius: 14px; |
|||
padding-right: 2px; |
|||
padding-bottom: 2px; |
|||
width: 11px; |
|||
height: 11px; |
|||
} |
|||
|
|||
#wm-btns #wm-sign-in>.iconochive-person { |
|||
font-size: 12.5px; |
|||
} |
|||
|
|||
#wm-save-snapshot-open > .iconochive-web { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-ipp #wm-share { |
|||
display: flex; |
|||
align-items: flex-end; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
#wm-share > #wm-screenshot { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-screenshot > .iconochive-image { |
|||
color:#000; |
|||
font-size:160%; |
|||
} |
|||
|
|||
#wm-share > #wm-video { |
|||
display: inline-block; |
|||
margin-right: 3px; |
|||
visibility: hidden; |
|||
} |
|||
|
|||
#wm-video > .iconochive-movies { |
|||
color: #000; |
|||
display: inline-block; |
|||
font-size: 150%; |
|||
margin-bottom: 2px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-in-progress { |
|||
display: none; |
|||
font-size:160%; |
|||
opacity: 0.5; |
|||
position: relative; |
|||
margin-right: 7px; |
|||
top: -5px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-success { |
|||
display: none; |
|||
color: green; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
#wm-btns #wm-save-snapshot-fail { |
|||
display: none; |
|||
color: red; |
|||
position: relative; |
|||
top: -7px; |
|||
} |
|||
|
|||
.wm-icon-screen-shot { |
|||
background: url("../images/web-screenshot.svg") no-repeat !important; |
|||
background-size: contain !important; |
|||
width: 22px !important; |
|||
height: 19px !important; |
|||
|
|||
display: inline-block; |
|||
} |
|||
#donato { |
|||
/* transition effect is disable so as to simplify height adjustment */ |
|||
/*transition: height 0.5s;*/ |
|||
height: 0; |
|||
margin: 0; |
|||
padding: 0; |
|||
border-bottom: 1px solid #999 !important; |
|||
} |
|||
body.wm-modal { |
|||
height: auto !important; |
|||
overflow: hidden !important; |
|||
} |
|||
#donato #donato-base { |
|||
width: 100%; |
|||
height: 100%; |
|||
/*bottom: 0;*/ |
|||
margin: 0; |
|||
padding: 0; |
|||
position: absolute; |
|||
z-index: 2147483639; |
|||
} |
|||
body.wm-modal #donato #donato-base { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 2147483640; |
|||
} |
|||
|
|||
.wb-autocomplete-suggestions { |
|||
font-family: Lucida Grande, Helvetica, Arial, sans-serif; |
|||
font-size: 12px; |
|||
text-align: left; |
|||
cursor: default; |
|||
border: 1px solid #ccc; |
|||
border-top: 0; |
|||
background: #fff; |
|||
box-shadow: -1px 1px 3px rgba(0,0,0,.1); |
|||
position: absolute; |
|||
display: none; |
|||
z-index: 2147483647; |
|||
max-height: 254px; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
box-sizing: border-box; |
|||
} |
|||
.wb-autocomplete-suggestion { |
|||
position: relative; |
|||
padding: 0 .6em; |
|||
line-height: 23px; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
font-size: 1.02em; |
|||
color: #333; |
|||
} |
|||
.wb-autocomplete-suggestion b { |
|||
font-weight: bold; |
|||
} |
|||
.wb-autocomplete-suggestion.selected { |
|||
background: #f0f0f0; |
|||
} |
|||
3
Docs/Chapter 2.2 Reading a file from CD-ROM_files/bundle-playback.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,116 @@ |
|||
@font-face{font-family:'Iconochive-Regular';src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?-ccsheb');src:url('https://archive.org/includes/fonts/Iconochive-Regular.eot?#iefix-ccsheb') format('embedded-opentype'),url('https://archive.org/includes/fonts/Iconochive-Regular.woff?-ccsheb') format('woff'),url('https://archive.org/includes/fonts/Iconochive-Regular.ttf?-ccsheb') format('truetype'),url('https://archive.org/includes/fonts/Iconochive-Regular.svg?-ccsheb#Iconochive-Regular') format('svg');font-weight:normal;font-style:normal} |
|||
[class^="iconochive-"],[class*=" iconochive-"]{font-family:'Iconochive-Regular'!important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} |
|||
.iconochive-Uplevel:before{content:"\21b5"} |
|||
.iconochive-exit:before{content:"\1f6a3"} |
|||
.iconochive-beta:before{content:"\3b2"} |
|||
.iconochive-logo:before{content:"\1f3db"} |
|||
.iconochive-audio:before{content:"\1f568"} |
|||
.iconochive-movies:before{content:"\1f39e"} |
|||
.iconochive-software:before{content:"\1f4be"} |
|||
.iconochive-texts:before{content:"\1f56e"} |
|||
.iconochive-etree:before{content:"\1f3a4"} |
|||
.iconochive-image:before{content:"\1f5bc"} |
|||
.iconochive-web:before{content:"\1f5d4"} |
|||
.iconochive-collection:before{content:"\2211"} |
|||
.iconochive-folder:before{content:"\1f4c2"} |
|||
.iconochive-data:before{content:"\1f5c3"} |
|||
.iconochive-tv:before{content:"\1f4fa"} |
|||
.iconochive-article:before{content:"\1f5cf"} |
|||
.iconochive-question:before{content:"\2370"} |
|||
.iconochive-question-dark:before{content:"\3f"} |
|||
.iconochive-info:before{content:"\69"} |
|||
.iconochive-info-small:before{content:"\24d8"} |
|||
.iconochive-comment:before{content:"\1f5e9"} |
|||
.iconochive-comments:before{content:"\1f5ea"} |
|||
.iconochive-person:before{content:"\1f464"} |
|||
.iconochive-people:before{content:"\1f465"} |
|||
.iconochive-eye:before{content:"\1f441"} |
|||
.iconochive-rss:before{content:"\221e"} |
|||
.iconochive-time:before{content:"\1f551"} |
|||
.iconochive-quote:before{content:"\275d"} |
|||
.iconochive-disc:before{content:"\1f4bf"} |
|||
.iconochive-tv-commercial:before{content:"\1f4b0"} |
|||
.iconochive-search:before{content:"\1f50d"} |
|||
.iconochive-search-star:before{content:"\273d"} |
|||
.iconochive-tiles:before{content:"\229e"} |
|||
.iconochive-list:before{content:"\21f6"} |
|||
.iconochive-list-bulleted:before{content:"\2317"} |
|||
.iconochive-latest:before{content:"\2208"} |
|||
.iconochive-left:before{content:"\2c2"} |
|||
.iconochive-right:before{content:"\2c3"} |
|||
.iconochive-left-solid:before{content:"\25c2"} |
|||
.iconochive-right-solid:before{content:"\25b8"} |
|||
.iconochive-up-solid:before{content:"\25b4"} |
|||
.iconochive-down-solid:before{content:"\25be"} |
|||
.iconochive-dot:before{content:"\23e4"} |
|||
.iconochive-dots:before{content:"\25a6"} |
|||
.iconochive-columns:before{content:"\25af"} |
|||
.iconochive-sort:before{content:"\21d5"} |
|||
.iconochive-atoz:before{content:"\1f524"} |
|||
.iconochive-ztoa:before{content:"\1f525"} |
|||
.iconochive-upload:before{content:"\1f4e4"} |
|||
.iconochive-download:before{content:"\1f4e5"} |
|||
.iconochive-favorite:before{content:"\2605"} |
|||
.iconochive-heart:before{content:"\2665"} |
|||
.iconochive-play:before{content:"\25b6"} |
|||
.iconochive-play-framed:before{content:"\1f3ac"} |
|||
.iconochive-fullscreen:before{content:"\26f6"} |
|||
.iconochive-mute:before{content:"\1f507"} |
|||
.iconochive-unmute:before{content:"\1f50a"} |
|||
.iconochive-share:before{content:"\1f381"} |
|||
.iconochive-edit:before{content:"\270e"} |
|||
.iconochive-reedit:before{content:"\2710"} |
|||
.iconochive-gear:before{content:"\2699"} |
|||
.iconochive-remove-circle:before{content:"\274e"} |
|||
.iconochive-plus-circle:before{content:"\1f5d6"} |
|||
.iconochive-minus-circle:before{content:"\1f5d5"} |
|||
.iconochive-x:before{content:"\1f5d9"} |
|||
.iconochive-fork:before{content:"\22d4"} |
|||
.iconochive-trash:before{content:"\1f5d1"} |
|||
.iconochive-warning:before{content:"\26a0"} |
|||
.iconochive-flash:before{content:"\1f5f2"} |
|||
.iconochive-world:before{content:"\1f5fa"} |
|||
.iconochive-lock:before{content:"\1f512"} |
|||
.iconochive-unlock:before{content:"\1f513"} |
|||
.iconochive-twitter:before{content:"\1f426"} |
|||
.iconochive-facebook:before{content:"\66"} |
|||
.iconochive-googleplus:before{content:"\67"} |
|||
.iconochive-reddit:before{content:"\1f47d"} |
|||
.iconochive-tumblr:before{content:"\54"} |
|||
.iconochive-pinterest:before{content:"\1d4df"} |
|||
.iconochive-popcorn:before{content:"\1f4a5"} |
|||
.iconochive-email:before{content:"\1f4e7"} |
|||
.iconochive-embed:before{content:"\1f517"} |
|||
.iconochive-gamepad:before{content:"\1f579"} |
|||
.iconochive-Zoom_In:before{content:"\2b"} |
|||
.iconochive-Zoom_Out:before{content:"\2d"} |
|||
.iconochive-RSS:before{content:"\1f4e8"} |
|||
.iconochive-Light_Bulb:before{content:"\1f4a1"} |
|||
.iconochive-Add:before{content:"\2295"} |
|||
.iconochive-Tab_Activity:before{content:"\2318"} |
|||
.iconochive-Forward:before{content:"\23e9"} |
|||
.iconochive-Backward:before{content:"\23ea"} |
|||
.iconochive-No_Audio:before{content:"\1f508"} |
|||
.iconochive-Pause:before{content:"\23f8"} |
|||
.iconochive-No_Favorite:before{content:"\2606"} |
|||
.iconochive-Unike:before{content:"\2661"} |
|||
.iconochive-Song:before{content:"\266b"} |
|||
.iconochive-No_Flag:before{content:"\2690"} |
|||
.iconochive-Flag:before{content:"\2691"} |
|||
.iconochive-Done:before{content:"\2713"} |
|||
.iconochive-Check:before{content:"\2714"} |
|||
.iconochive-Refresh:before{content:"\27f3"} |
|||
.iconochive-Headphones:before{content:"\1f3a7"} |
|||
.iconochive-Chart:before{content:"\1f4c8"} |
|||
.iconochive-Bookmark:before{content:"\1f4d1"} |
|||
.iconochive-Documents:before{content:"\1f4da"} |
|||
.iconochive-Newspaper:before{content:"\1f4f0"} |
|||
.iconochive-Podcast:before{content:"\1f4f6"} |
|||
.iconochive-Radio:before{content:"\1f4fb"} |
|||
.iconochive-Cassette:before{content:"\1f4fc"} |
|||
.iconochive-Shuffle:before{content:"\1f500"} |
|||
.iconochive-Loop:before{content:"\1f501"} |
|||
.iconochive-Low_Audio:before{content:"\1f509"} |
|||
.iconochive-First:before{content:"\1f396"} |
|||
.iconochive-Invisible:before{content:"\1f576"} |
|||
.iconochive-Computer:before{content:"\1f5b3"} |
|||
@ -0,0 +1,70 @@ |
|||
body { |
|||
max-width: 900px; |
|||
margin: auto; |
|||
padding: 8px; |
|||
font-family: sans-serif; |
|||
font-size: 14px; |
|||
//color: white; |
|||
//background: black; |
|||
} |
|||
|
|||
h { |
|||
background-color: #e0e0e0; |
|||
padding: 2px; |
|||
} |
|||
|
|||
h2 { |
|||
border-bottom: 1px solid; |
|||
//padding-left: 8px; |
|||
} |
|||
|
|||
img { |
|||
display: block; |
|||
} |
|||
|
|||
.footer-table { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.bordered-table { |
|||
border-collapse: collapse; |
|||
font-size: 11px; |
|||
} |
|||
|
|||
.bordered-table th, .bordered-table td { |
|||
border: 1px solid; |
|||
padding: 4px; |
|||
} |
|||
|
|||
hr { |
|||
border: none; |
|||
border-bottom: 1px solid black; |
|||
} |
|||
|
|||
pre { |
|||
padding: 8px; |
|||
font-size: 12px; |
|||
color: black; |
|||
background-color: LightGray; |
|||
} |
|||
/* |
|||
FILE ARCHIVED ON 03:35:25 Aug 27, 2022 AND RETRIEVED FROM THE |
|||
INTERNET ARCHIVE ON 15:39:09 Sep 05, 2022. |
|||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. |
|||
|
|||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. |
|||
SECTION 108(a)(3)). |
|||
*/ |
|||
/* |
|||
playback timings (ms): |
|||
captures_list: 107.165 |
|||
exclusion.robots: 0.073 |
|||
exclusion.robots.policy: 0.067 |
|||
cdx.remote: 0.064 |
|||
esindex: 0.009 |
|||
LoadShardBlock: 52.713 (3) |
|||
PetaboxLoader3.datanode: 140.466 (4) |
|||
CDXLines.iter: 14.771 (3) |
|||
load_resource: 139.896 |
|||
PetaboxLoader3.resolve: 47.824 |
|||
*/ |
|||
21
Docs/Chapter 2.2 Reading a file from CD-ROM_files/wombat.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue