gba/docs/ch1/the_display_control.html

281 lines
15 KiB
HTML
Raw Normal View History

2018-11-10 20:03:37 +11:00
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>The Display Control - Rust GBA Tutorials</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">var path_to_root = "../";</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = 'light'; }
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
2018-11-11 17:39:26 +11:00
<ol class="chapter"><li><a href="../introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="../ch0/index.html"><strong aria-hidden="true">2.</strong> Ch 0: Development Setup</a></li><li><a href="../ch1/index.html"><strong aria-hidden="true">3.</strong> Ch 1: Hello GBA</a></li><li><ol class="section"><li><a href="../ch1/hello1.html"><strong aria-hidden="true">3.1.</strong> hello1</a></li><li><a href="../ch1/io_registers.html"><strong aria-hidden="true">3.2.</strong> IO Registers</a></li><li><a href="../ch1/the_display_control.html" class="active"><strong aria-hidden="true">3.3.</strong> The Display Control</a></li><li><a href="../ch1/video_memory_intro.html"><strong aria-hidden="true">3.4.</strong> Video Memory Intro</a></li><li><a href="../ch1/hello2.html"><strong aria-hidden="true">3.5.</strong> hello2</a></li></ol></li></ol>
2018-11-10 20:03:37 +11:00
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light <span class="default">(default)</span></button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Rust GBA Tutorials</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<a class="header" href="#the-display-control" id="the-display-control"><h1>The Display Control</h1></a>
<p>The Display Control is our first actual IO Register. GBATEK gives it the
shorthand <a href="http://problemkaputt.de/gbatek.htm#lcdiodisplaycontrol">DISPCNT</a>, so
you might see it under that name if you read other guides.</p>
<p>Among IO Registers, it's one of the simpler ones, but it's got enough complexity
that we can get a hint of what's to come.</p>
<p>Also it's the one that you basically always need to set at least once in every
GBA game, so it's a good starting one to go over for that reason too.</p>
<p>The Display Control is a <code>u16</code> value located at <code>0x0400_0000</code>.</p>
<a class="header" href="#video-modes" id="video-modes"><h2>Video Modes</h2></a>
<p>The lowest three bits (0-2) let you select from among the GBA's six video modes.
You'll notice that 3 bits allows for eight modes, but the values 6 and 7 are
prohibited.</p>
<p>Modes 0, 1, and 2 are &quot;Tiled&quot; modes. These are actually the modes that you
should eventually learn to use as much as possible. It lets the GBA's limited
video hardware do as much of the work as possible, leaving more of your CPU time
for gameplay computations. However, they're also complex enough to deserve their
own demos and chapters later on, so that's all we'll say about them for now.</p>
<p>Modes 3, 4, and 5 are &quot;Bitmap&quot; modes. These let you write individual pixels to
locations on the screen.</p>
<ul>
2018-11-11 17:39:26 +11:00
<li><strong>Mode 3</strong> is full resolution (240w x 160h) RBG15 color. You might not be used
to RGB15, since modern computers have 24 or 32 bit colors. In RGB15, there's 5
bits for each color channel stored within a <code>u16</code> value, and the highest bit is
simply ignored.</li>
2018-11-10 20:03:37 +11:00
<li><strong>Mode 4</strong> is full resolution paletted color. Instead of being a <code>u16</code> color, each
pixel value is a <code>u8</code> palette index entry, and then the display uses the
palette memory (which we'll talk about later) to store the actual color data.
Since each pixel is half sized, we can fit twice as many. This lets us have
two &quot;pages&quot;. At any given moment only one page is active, and you can draw to
the other page without the user noticing. You set which page to show with
another bit we'll get to in a moment.</li>
<li><strong>Mode 5</strong> is full color, but also with pages. This means that we must have a
reduced resolution to compensate (video memory is only so big!). The screen is
effectively only 160w x 128h in this mode.</li>
</ul>
<a class="header" href="#cgb-mode" id="cgb-mode"><h2>CGB Mode</h2></a>
2018-11-11 17:39:26 +11:00
<p>Bit 3 is effectively read only. Technically it can be flipped using a BIOS call,
but when you write to the display control normally it won't write to this bit,
so we'll call it effectively read only.</p>
<p>This bit is on if the CPU is in CGB mode.</p>
2018-11-10 20:03:37 +11:00
<a class="header" href="#page-flipping" id="page-flipping"><h2>Page Flipping</h2></a>
<p>Bit 4 lets you pick which page to use. This is only relevent in video modes 4 or
5, and is just ignored otherwise. It's very easy to remember: when the bit is 0
the 0th page is used, and when the bit is 1 the 1st page is used.</p>
<p>The second page always starts at <code>0x0600_A000</code>.</p>
<a class="header" href="#oam-vram-and-blanking" id="oam-vram-and-blanking"><h2>OAM, VRAM, and Blanking</h2></a>
<p>Bit 5 lets you access OAM during HBlank if enabled. This is cool, but it reduces
the maximum sprites per scanline, so it's not default.</p>
<p>Bit 6 lets you adjust if the GBA should treat Object Character VRAM as being 2d
(off) or 1d (on).</p>
<p>Bit 7 forces the screen to stay in vblank as long as it's set. This allows the
fastest use of the VRAM, Palette, and Object Attribute Memory. Obviously if you
leave this on for too long the player will notice a blank screen, but it might
be okay to use for a moment or two every once in a while.</p>
<a class="header" href="#screen-layers" id="screen-layers"><h2>Screen Layers</h2></a>
<p>Bits 8 through 11 control if Background layers 0 through 3 should be active.</p>
<p>Bit 12 affects the Object layer.</p>
<p>Note that not all background layers are available in all video modes:</p>
<ul>
<li>Mode 0: all</li>
<li>Mode 1: 0/1/2</li>
<li>Mode 2: 2/3</li>
<li>Mode 3/4/5: 2</li>
</ul>
<p>Bit 13 and 14 enable the display of Windows 0 and 1, and Bit 15 enables the
object display window. We'll get into how windows work later on, they let you do
some nifty graphical effects.</p>
<a class="header" href="#in-conclusion" id="in-conclusion"><h2>In Conclusion...</h2></a>
<p>So what did we do to the display control in <code>hello1</code>?</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
(0x04000000 as *mut u16).write_volatile(0x0403);
#}</code></pre></pre>
<p>First let's <a href="https://www.wolframalpha.com/input/?i=0x0403">convert that to
binary</a>, and we get
<code>0b100_0000_0011</code>. So, that's setting Mode 3 with background 2 enabled and
nothing else special.</p>
2018-11-11 17:39:26 +11:00
<p>However, I think we can do better than that. This is a prime target for more
newtyping as we attempt a <code>hello2</code> program.</p>
2018-11-10 20:03:37 +11:00
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../ch1/io_registers.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../ch1/video_memory_intro.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="../ch1/io_registers.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="../ch1/video_memory_intro.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="../book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>