100% found this document useful (16 votes)
62 views

Get Cross Platform Game Programming Game Development 1st Edition Steven Goodwin PDF ebook with Full Chapters Now

Platform

Uploaded by

saltonedjib
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (16 votes)
62 views

Get Cross Platform Game Programming Game Development 1st Edition Steven Goodwin PDF ebook with Full Chapters Now

Platform

Uploaded by

saltonedjib
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 85

Download the full version of the ebook at ebookfinal.

com

Cross Platform Game Programming Game Development


1st Edition Steven Goodwin

https://ebookfinal.com/download/cross-platform-game-
programming-game-development-1st-edition-steven-goodwin/

OR CLICK BUTTON

DOWNLOAD EBOOK

Download more ebook instantly today at https://ebookfinal.com


Instant digital products (PDF, ePub, MOBI) available
Download now and explore formats that suit you...

Cross Platform Game Development Make PC Games for Windows


Linux and Mac Wordware Game Developer s Library 1st
Edition Alan Thorn
https://ebookfinal.com/download/cross-platform-game-development-make-
pc-games-for-windows-linux-and-mac-wordware-game-developer-s-
library-1st-edition-alan-thorn/
ebookfinal.com

Game Programming Golden Rules Game Development Series 1st


Edition Martin Brownlow

https://ebookfinal.com/download/game-programming-golden-rules-game-
development-series-1st-edition-martin-brownlow/

ebookfinal.com

OpenGL Game Programming Prima Tech s Game Development 1st


Edition Kevin Hawkins

https://ebookfinal.com/download/opengl-game-programming-prima-tech-s-
game-development-1st-edition-kevin-hawkins/

ebookfinal.com

Beginning 3D Game Development with Unity All in One Multi


Platform Game Development 2nd edition Edition Sue Blackman

https://ebookfinal.com/download/beginning-3d-game-development-with-
unity-all-in-one-multi-platform-game-development-2nd-edition-edition-
sue-blackman/
ebookfinal.com
Game Programming Gems 3 Game Programming Gems Series v 3
1st Edition Dante Treglia

https://ebookfinal.com/download/game-programming-gems-3-game-
programming-gems-series-v-3-1st-edition-dante-treglia/

ebookfinal.com

Game Programming Gems 2 Game Programming Gems Series Vol 2


1st Edition Mark Deloura

https://ebookfinal.com/download/game-programming-gems-2-game-
programming-gems-series-vol-2-1st-edition-mark-deloura/

ebookfinal.com

C Game Programming For Serious Game Creation 1st Edition


Daniel Schuller

https://ebookfinal.com/download/c-game-programming-for-serious-game-
creation-1st-edition-daniel-schuller/

ebookfinal.com

C Game Programming For Serious Game Creation 1st Edition


Daniel Schuller

https://ebookfinal.com/download/c-game-programming-for-serious-game-
creation-1st-edition-daniel-schuller-2/

ebookfinal.com

Game Level Design Game Development Series 1st Edition Ed


Byrne

https://ebookfinal.com/download/game-level-design-game-development-
series-1st-edition-ed-byrne/

ebookfinal.com
CROSS-PLATFORM
GAME PROGRAMMING
LIMITED WARRANTY AND DISCLAIMER OF LIABILITY

THE CD-ROM THAT ACCOMPANIES THE BOOK MAY BE USED ON A SINGLE PC


ONLY. THE LICENSE DOES NOT PERMIT THE USE ON A NETWORK (OF ANY
KIND). YOU FURTHER AGREE THAT THIS LICENSE GRANTS PERMISSION TO USE
THE PRODUCTS CONTAINED HEREIN, BUT DOES NOT GIVE YOU RIGHT OF
OWNERSHIP TO ANY OF THE CONTENT OR PRODUCT CONTAINED ON THIS
CD-ROM. USE OF THIRD-PARTY SOFTWARE CONTAINED ON THIS CD-ROM
IS LIMITED TO AND SUBJECT TO LICENSING TERMS FOR THE RESPECTIVE
PRODUCTS.

CHARLES RIVER MEDIA, INC. (“CRM”) AND/OR ANYONE WHO HAS BEEN
INVOLVED IN THE WRITING, CREATION, OR PRODUCTION OF THE ACCOMPA-
NYING CODE (“THE SOFTWARE”) OR THE THIRD-PARTY PRODUCTS CON-
TAINED ON THE CD-ROM OR TEXTUAL MATERIAL IN THE BOOK, CANNOT AND
DO NOT WARRANT THE PERFORMANCE OR RESULTS THAT MAY BE OBTAINED
BY USING THE SOFTWARE OR CONTENTS OF THE BOOK. THE AUTHOR AND
PUBLISHER HAVE USED THEIR BEST EFFORTS TO ENSURE THE ACCURACY AND
FUNCTIONALITY OF THE TEXTUAL MATERIAL AND PROGRAMS CONTAINED
HEREIN. WE HOWEVER, MAKE NO WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, REGARDING THE PERFORMANCE OF THESE PROGRAMS OR CON-
TENTS. THE SOFTWARE IS SOLD “AS IS” WITHOUT WARRANTY (EXCEPT FOR
DEFECTIVE MATERIALS USED IN MANUFACTURING THE DISK OR DUE TO
FAULTY WORKMANSHIP).

THE AUTHOR, THE PUBLISHER, DEVELOPERS OF THIRD-PARTY SOFTWARE,


AND ANYONE INVOLVED IN THE PRODUCTION AND MANUFACTURING OF
THIS WORK SHALL NOT BE LIABLE FOR DAMAGES OF ANY KIND ARISING OUT
OF THE USE OF (OR THE INABILITY TO USE) THE PROGRAMS, SOURCE CODE, OR
TEXTUAL MATERIAL CONTAINED IN THIS PUBLICATION. THIS INCLUDES, BUT
IS NOT LIMITED TO, LOSS OF REVENUE OR PROFIT, OR OTHER INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THE PRODUCT.

THE SOLE REMEDY IN THE EVENT OF A CLAIM OF ANY KIND IS EXPRESSLY


LIMITED TO REPLACEMENT OF THE BOOK AND/OR CD-ROM, AND ONLY AT
THE DISCRETION OF CRM.

THE USE OF “IMPLIED WARRANTY” AND CERTAIN “EXCLUSIONS” VARIES FROM


STATE TO STATE, AND MAY NOT APPLY TO THE PURCHASER OF THIS PRODUCT.
CROSS-PLATFORM
GAME PROGRAMMING

STEVEN GOODWIN

CHARLES RIVER MEDIA, INC.


Hingham, Massachusetts
Copyright 2005 by CHARLES RIVER MEDIA, INC.
All rights reserved.

No part of this publication may be reproduced in any way, stored in a retrieval system of any
type, or transmitted by any means or media, electronic or mechanical, including, but not limited
to, photocopy, recording, or scanning, without prior permission in writing from the publisher.
Publisher: Jenifer Niles
Cover Design: The Printed Image
CHARLES RIVER MEDIA, INC.
10 Downer Avenue
Hingham, Massachusetts 02043
781-740-0400
781-740-8816 (FAX)
[email protected]
www.charlesriver.com
This book is printed on acid-free paper.
Steven Goodwin. Cross-Platform Game Programming.
ISBN: 1-58450-379-3
eISBN: 1-58450-639-3
All brand names and product names mentioned in this book are trademarks or service
marks of their respective companies. Any omission or misuse (of any kind) of service marks or
trademarks should not be regarded as intent to infringe on the property of others. The publisher
recognizes and respects all marks used by companies, manufacturers, and developers as a means
to distinguish their products.
Library of Congress Cataloging-in-Publication Data
Goodwin, Steven, 1973-
Cross platform game programming / Steven Goodwin.— 1st ed.
p. cm.
Includes bibliographical references and index.
ISBN 1-58450-379-3 (pbk. with cd-rom : alk. paper)
1. Computer games—Programming. 2. Cross-platform software development. I. Title.
QA76.76.C672G66 2005
794.8’1526—dc22
2004029828
Printed in the United States of America
05 7 6 5 4 3 2 First Edition
CHARLES RIVER MEDIA titles are available for site license or bulk purchase by institutions,
user groups, corporations, etc. For additional information, please contact the Special Sales De-
partment at 781-740-0400.
Requests for replacement of a defective CD-ROM must be accompanied by the original disc,
your mailing address, telephone number, date of purchase, and purchase price. Please state the
nature of the problem, and send the information to CHARLES RIVER MEDIA, INC., 10
Downer Avenue, Hingham, Massachusetts 02043. CRM’s sole obligation to the purchaser is to
replace the disc, based on defective materials or faulty workmanship, but not on the operation
or functionality of the product.
To my sister, Angela…

…the brainy one of the family.


This page intentionally left blank
Contents

Dedication v
Acknowledgments xvii
Preface xix

1 Introduction 1
Background of Cross-Platform Programming 1
History 2
The Importance of Cross-Platform Development 4
Overview of Cross-Platform Components 7
The Lead Platform 9
Cross-Generation, Cross-Platform Game Programming 9
The Theoretical Process 10
The Development Process 12
Code Is Code 12
Console Limitations 14
Libraries 15
About the Book 17
Coding Style 17
Non-Disclosure Agreements 18
Notes to the Reader 18
Endnotes 19

2 Top Ten Tips 21


The Basic Issues 21

vii
viii Contents

Abstraction 22
Commonality 24
Limitations 24
Language Limitations 24
Library Limitations 27
Compiler Limitations 27
Platform Limitations 31
Modularization 33
Resource Creation Path 35
Resource Detail 35
Granularity 38
Basic Datatypes 39
Memory Management 39
Audio Code 39
Separation and Isolation 40
Obvious Isolation 40
Singletons 41
Class Structures 43
Divorcing Code 44
Separation by Purpose 46
Separation by Memory 49
Separation for the Present 49
Separation for the Future 50
Succession 52
The pImpl Idiom 53
Debugging and Profiling 53
Programming-Based Bugs 53
Compiler-Based Bugs 54
Execution-Based Bugs 55
Profiling 59
Predictability 60
Contents ix

Randomness 60
Trigonometry 61
Input Stimuli 61
Turn-Around 62
Endnotes 65

3 Memory 67
The Specification 67
Simple Memory 71
The Issues–Datatypes 71
The Issues–A Safety File 74
The Issues–The Report 76
Our Own Memory Manager–Design 81
Hardware Properties 81
Endian 81
Alignment 85
Access 87
Software Properties 87
Fragmentation 87
The Standard Library 89
Our Own Memory Manager–Implementation 90
Conceptual Design 91
Allocating Memory 94
Garbage Collection 97
Releasing Memory 98
Debugging Memory 99
Profiling Memory Usage 102
Allocation Wrappers 102
High-Level Memory Usage 102
Application Memory Usage 104
Using Allocation Within Subsystems 115
Global versus Game 117
x Contents

Other Guidelines 118


The Stack 118
Local Variabales 120
Intelligent Buffer Usage 121
Minimize Dynamic Memory 121
Endnotes 121

4 The CPU 123


The CPU 123
Timer Resolution 124
Processor Yield 126
Programming the Clock 127
Programming Timers 130
Programming Profilers 130
Time Slicing 132
CPU Scalability 138
Lowest Common Denominator 138
Scale Back 139
Level of Detail (LOD) 139
Extra Burn 140
Parallel Processing 141
Parallel Determination 141
Parallel Distribution 143
Parallel Implementation 149
Task Scheduling 160
Avoiding the Whole Problem 162
Endnotes 163

5 Storage 165
The Four Corners of Storage 165
The Problems 166
Contents xi

The Data Conversion Process 170


Serialization 173
Endian Issues 178
Extensibility and Future-Proofing 184
Introducing Platform-Specific Data 188
Introducing Platform-Specific Resources 196
Serializing Class Hierarchies 197
Object Creation 199
Interdependent Objects 200
Patching Pointers 201
Designing a Filesystem 205
Disc Size 208
Layout 209
Filesystem Implementation 212
Filesystem Devices 214
File Handling 220
Filesystem Shortcuts 224
Filesystem Additions 225
Handling Physical Devices 225
Asynchronous Loading 226
Synchronous Loading 231
Block Sizes and Caching 233
The General Case 236
Creating Back Doors 236
Going Around the Problem 237
Knowing the Device 237
A ZIP Warning 237
Endnotes 238

6 Debugging 241
Basic Requirements 241
Debugging Methods 242
xii Contents

Coding Style 242


Debugging Methodologies 248
Implementing Debugging Code 250
Trace Messages 251
Trace Levels 252
Handling Errors 261
Assertions 262
Memory 265
Output Targets 271
Time Delay 272
Flushes 272
Sending to Host 272
Bugs in the Compiler 272
Bugs in the Debugging Code 273
Reproduction Bugs 273
Hardware Problems 273
Screen 273
Second Sight 274
File 274
Serial Port 275
Making Data Readable 275
Multithreaded Output 276
Maintaining Consistency 278
Isolating System Calls 278
Tabulating Trigonometry 282
Random Numbers 287
Code Checking 292
Endnotes 293

7 System I/O 295


Abstracting Basics 295
The Null Driver 296
Contents xiii

Prepared Singleton 296


Double Chance Functions 297
Input Devices 299
General Implementation 300
Input Logging 311
Gameplay Abstractions 315
The Bottom Line 318
Endnotes 319

8 The Audio System 321


High-Level Parameters 321
Playing Music 322
CD Audio 323
MP3 and Ogg Vorbis 323
MIDI 324
Customized Formats 325
Playing Sounds 326
Raw Data 326
Compressed Data 326
Metadata 327
Looped Sounds 327
Resourcing Data 328
In Memory 328
From a Stream 328
Asynchronous Loading 330
Mixer Control 330
UDE 331
The Gameplay Mixer 334
The Technology Mixer 338
The User Mixer 339
Video Playback Interaction 341
xiv Contents

Endnote 341

9 The Graphics Engine 343


History 343
Common Code 344
Techniques 346
Static Texture Changes 346
Dynamic Texture Changes 349
Translucent Textures 352
State Changes 353
Mode Changes 356
Special Cases 358
Resourcing the Data 359
Textures 359
Meshes 362
Engine Features 362
Camera 363
Viewports 364
Lights 365
The Scene 366
Abstracted Features 367
Texture Handling 368
Meshes 369
Sprites 372
Fonts and 2D Overlays 373
Abstracting Special Effects 374
Engine Effects 374
Game Effects 374
Special Effects 374
Graphics on Television 375
Text 375
Contrasting Colors 376
Contents xv

Image Sizes 376


Balancing Colors 377
Physical Testing 377
Endnotes 378

10 Network Programming 379


Packet Programming 379
Networking Background 380
The Physical Network 382
The Conceptual Network Driver 382
The Null Network 391
Network Latency 392
Dropped Packets 393
The Two Modes 394
Cross-Network Progamming 395
Endnote 395

11 The Bits We Forget About 397


The Development Process 397
The Environment 397
Source Code 401
Presentation Issues 403
PAL and NTSC 403
Frontend Screens 405
Foreign Language Versions 406
Operating System Considerations 409
The Size of size_t 409
Code Overlays 409
Initializing the OS 410
Handling Technical Requirements 413
Title Screens 413
Attract Mode 414
xvi Contents

Reset Buttons 414


Memory Cards 415
Disc Covers 419
Artifacts of Code 420
The Consequence of STL 420
Exceptions 422
Game Configuration 424
Hacking It 424
Endnotes 425

Appendix A About the CD-ROM 427

Appendix B PlayStation 2 Glossary431

Appendix C Xbox Glossary 435

Appendix D GameCube Glossary 439

Appendix E Code Guidelines 443

Index 445
Acknowledgments

he completion of this book is the result of many people and their inspira-

T tion, experience, ideas, and time. Writing the actual words appears insignif-
icant by comparison.
I would like to thank my readers, editors, and other assorted developers who
have provided invaluable feedback, comments, and suggestions, especially Michael
Braithwaite, Ben Crossman, Dan Evans, Mal Lansell, David Manley, Jerome Muf-
fat-Meridol, and Dave Wall.
To my friends and colleagues that have encouraged my writing: John Hearns,
Anne Mullane, Colin Murphy, Steve Porter, John Southern, and Dean Wilson.
To those with whom I’ve worked, and whose great ideas have found some form
within these words, I thank you: The development teams at Bits Studios, Computer
Artworks (R.I.P.), Criterion and Edcom, and notably Mat Cook, Dominic Giles,
Vlad Kapietsky, Nat Presson, Alan Troth, Mark Walker, and Darren Ward.
I would like to thank Jenifer Niles and all her team at Charles River Media for
this book, and for making me appear competent!
Finally, I would like to thank my close network of family and friends who know
all about me, but seem to like me anyway—especially David Eade, Ed and Margaret
Grabowski (without whom...), Justine Griffith, Phillip Hart, William Siddons,
Fiona Stewart, Maria Thomson, and all of TULS, Lonix, Gllug, 2600, and Slashdot-
London.
And, of course, I want to thank Grandma, Granddad, Shirley and Ken, Juliette
and Dean, Melanie, Mum, Dad, and my sister Angela.

xvii
This page intentionally left blank
Preface

ith nearly every game on the market today being released si-

W multaneously on all platforms, the need for a good cross-plat-


form development strategy is crucially important. Every hour
spent reinventing the wheel is an hour wasted. Or put another way, every
hour spent writing cross-platform code constitutes three saved hours. This
means being able to write code that behaves identically on all machines.
Not similar—identical! This book covers myriad problems that exist
within every cross-platform games, and gives you the understanding and
ability needed to solve them.
This book is intended for developers working (or hoping to work) in
the games industry who need a mentor to guide them through the jungle of
abstractions, design patterns, and engine architectures that support a cross-
platform game. You’ll learn the particular rules and methods by which
code must be written, why these rules exist, and how to harness them to
create good cross-platform code.
The book is also for those looking to start crossing their project from
one platform to another, and for those building a new engine with the in-
tention of making it cross-platform from the ground up. This book will
help senior and lead programmers determine where the platform-specific
features should start and end, and the best way to achieve their cross-plat-
form goals. Gameplay programmers will develop according to these same
rules, preventing the common problems and thereby speeding their ascent
to lead and senior level.

xix
xx Preface

For those already working in the upper echelons of their company, this book
provides a solid reference of development practices and a detailed breakdown of all
the required cross-platform game components, with a comprehensive task list for
the team. You also get detailed explanations of new technologies, such as multi-
processing and threaded environments, and how they will affect the next genera-
tion of consoles.
For those using middleware, the problem is not over because every program-
mer still needs to be able to handle memory, the filesystem, and gameplay code in
a generic, cross-platform manner to make efficient use of the purchase. Who knew
that in our world the standard libraries are not standard? This book covers the
rarely discussed world of cross-platform game programming and gives you the un-
derstanding to develop your games effectively.
We begin by explaining the 10 basic tenets for development that must be ad-
hered to throughout a project for it to work, whether it involves engine or gameplay
coding. We then cover specific areas in detail, such as the abstraction of a filesys-
tem, the graphics engine, the memory manager, and how to handle different hard-
ware specifications without changing the code. Seemingly general topics (such as
debugging and UI design) take on new meaning and raise different issues when the
platform changes and the old tricks no longer work.
A plethora of new ideas and techniques need to be adopted across the spheres
of memory allocation, file handling, graphics, audio, and networking. These are all
areas of knowledge that were once deemed magic by the knowledgeable few, and
unobtainable by the rest of the populous. They are now available to all, and I hope
to teach you some new tricks in this book.
–Steven Goodwin
1 Introduction

In This Chapter
Background of Cross-Platform Programming
Overview of Cross-Platform Components
The Development Process
About the Book
Non-Disclosure Agreements
Notes to the Reader

BACKGROUND OF CROSS-PLATFORM PROGRAMMING

Cross-platform development is the art, skill, ability, and general know-how re-
quired to write software that works on multiple platforms. “Working on multiple
platforms” means that the same code will compile, link, run, and behave identically
on whichever platform is targeted. Granted, the compiler and tools will be specific
to each machine, and the underlying Application Programming Interface (API)
may vary, but the code itself will be identical as both the game and engine should
be reusable across each platform; that is, developed once, and deployed often.
To be considered a cross-platform project (as opposed to a port), work must be
carried out concurrently on at least two different target machines using a common
code base that remains live throughout. This is a delicate skill because algorithms,
libraries, compilers, and data structures cannot be changed in an arbitrary fashion

1
2 Cross-Platform Game Programming

as a benign modification to one system could cause catastrophic problems for one
(or more) of the other platforms. This is especially true of the data structures con-
taining game assets, where the effects can range from a nuisance to code break-
down, to fluctuations in the memory footprint and large-scale project delays.
Also, a cross-platform game must act identically on these different machines
once compiled. This is the main difference between a project that can be compiled
and run on different machines, and one that is truly cross-platform. Most of the
available OpenGL® code, for example, will compile and run anywhere, but its run-
time behavior often relies on the target platform and varies according to the oper-
ating system, memory, processor speed, filesystem, byte order, and graphics
capabilities.

History
Before the current crop of games, cross-platform development only occurred
rarely. Usually, a game was written first, and then ported to other platforms. The
amount of work required varied according to the project, but was usually small.
Often, when the same development team carried out the port, a set of libraries
would be rewritten for each machine using common names and calling conven-
tions. Various portions of the game code were then changed, amended, and gener-
ally hacked around to compile or assemble on the new platform. There would be
moderate reuse of the game code, but very little reuse of the engine.
Throughout most of the 1980s, a different programmer (or team) would
rewrite the entire game whenever the game was ported to a new platform. Because
most games of this time were written in assembler, it was rare to find a programmer
expert enough in more than a couple of machine code variations to write both ver-
sions. The newness of the industry also meant that very few conversion tools were
available because these were highly specialized languages. The game engines con-
sisted of highly optimized sprite renderers and animation code that would usually
belong to the conversion programmer himself and tied into the new game with
whatever customizations were needed for that project.
As games became more complex in the 1990s, bringing in a different developer
(or team) for the new platform became a less viable option. Development cycles
were no longer measured in weeks, but months. Publishers didn’t want to wait an-
other six months for the conversions to appear because this prevented any attempt
at a short-term marketing and advertising blitz. This meant both versions of the
game had to be developed in tandem, requiring more code reuse as was demon-
strated within the game development cycles of the Commodore™ Amiga® and
Atari® ST, which shared a common processor in the Motorola® 68000. Software
houses created their own graphics library (now called engines) and developed both
Introduction 3

products concurrently in the first cases of true cross-platform development. In this


situation, both game and engine code would get reused on each platform.
Even though technology was marching on, the industry was diverted from this
early cross-platform view because it was not distributed evenly between projects.
On one hand, the IBM® PC (and its myriad clones) encouraged highly complex
strategy games, flight simulators, and war games using high-powered Intel® chips
and hard drives for mass storage. Programmed in C and C++, these games used
multimedia drivers for graphics, sound, and networking. The structure of these dri-
vers varied between hardware, requiring an abstraction of their basic functional-
ity—a technique still used today. On the other hand, the market for standalone
consoles was growing by using smaller machines with customized chips for im-
proved graphics and sound, and by focusing its market on children and teenagers
playing platform and shooting games. These games were largely written in assem-
bler with very little code sharing because every ounce of processing power needed
to be squeezed out of the machine for each game. However, more engine code was
being reused because each game was shipped for several platforms in the same time
frame, as common libraries (with identical names, but written in different lan-
guages) again came to the forefront. Code reuse became more pronounced as the
console market grew and became license-driven with very short lead times. Every
other game, it seemed, was connected to a film release and so needed to be available
on as many machines as possible (and as quickly as possible) to maximize the rev-
enue streams. The jokes about “change the name, change the graphics, and reship”
weren’t funny, as it brought about a downturn in fortunes within the industry.
The first step back to the cross-platform path began with the Sony® PlaySta-
tion™, Nintendo® 64, and Sega® Saturn™ series of consoles, as gamers became
more adult, and console programmers rediscovered the joy of the C language. Dur-
ing this time, speed was not as vital as it had been previously. It was important cer-
tainly, but whereas programmers would previously have spent days trying to claw
back one or two processor cycles, attention now focused on other areas for many
reasons. First, when working in a high-level language, such as C, you have less op-
portunity to optimize at the low level because the assembler code is now the com-
piler’s responsibility. Second, the balance of processing moved away from the CPU
and onto the graphics chip. This meant that an extra cycle saved on the CPU did-
n’t make any difference to the speed if the game was still bound by slow graphics
processing. Third, the increase of code size and team members required a more
maintainable development environment. Maintenance-friendly programming
rarely involves assembler.
This scenario is consistent with the present day, and the desire for a maintain-
able engine takes precedence over speed or memory issues because those gains can
be made in areas other than code. In recent years, only one notable console engine
has been written entirely in assembler: Jak and Daxter™ for the PS2™. It was not
4 Cross-Platform Game Programming

cross-platform, and still used a scripting language to implement gameplay. Almost


all games are presently written in C++ (with some still chained to C code, where an
old engine is still in use), and most of these are cross-platform.

The Importance of Cross-Platform Development


Cross-platform game development is important for many people, not just pro-
grammers. For the marketing department, it means they can sell four games at
once with one budget, and don’t need to remind the public about the game with
each new platform release. One advertisement, with the line “Available on PC, PS2,
Xbox™ and GameCube™” hits all the bases. It also means marketing can answer
“Yes” to any question concerning its availability, giving a very positive message to
the retail chains.
Cross-platform development helps publishers, too. They are still holding the
game industry’s purse strings, and so need some way of recouping their costs. Hav-
ing the game available on every platform, especially at the start of a console’s life-
time, means that publishers can hedge their bets concerning from where the big
money will come. It has never been “obvious” that the Sony PlayStation and PS2
would be the big sellers they have become in the marketplace. Even with the success
of the original PlayStation, publishers and developers would both mutter the words
“lightning” and “twice” in sentences that also contained the phrase “PS2.” This is
true in any industry. When VCRs were first available to the public, the war between
VHS and Betamax™ was the stuff of legends. Film companies released movies on
both formats, siding with both camps, just in case they backed the wrong prover-
bial horse. Game publishers are doing the same now. Even when one platform has
a strong dominance, it’s still good to sell the same product to as many people as
possible providing the costs involved aren’t excessive. There’s no reason why any
particular platform should be excluded without good reason.
And finally, cross-platform development helps the developers—although it
might never appear that way. With the exception of the very biggest developers
(that is, the likes of Id®, Blizzard®, and Valve), no one gets to dictate their market-
place; Id could release Quake™ 17—requiring five 12.8 GHz graphic cards attached
to monitors placed in a cube around the players head—and it would still sell
enough copies to make back development costs and draw a tidy profit. Market
forces—whatever the public is prepared to pay for—drive the rest of us.
The state of the industry is most apparent in the mass-market field of casual
gamers, as they own nothing more than a single platform and a handful of games.
If your first-person shooter isn’t released on their platform, they’ll buy someone
else’s, and all your hard work will be for naught. Unless you’re working on the next
Zelda®, heed this advice.
Introduction 5

Technology
From a technical programmers perspective, cross-platform development encour-
ages a modular approach to development. Because it’s not possible to run Nintendo
code on a Sony platform, for example, every individual component must be iso-
lated: processing and presentation, platform-specific and common, game and en-
gine. Each module must then provide a common interface to the rest of game,
hiding the specific details beneath it. This conforms to the traditional view of good
software design. A cross-platform project enforces this distinction that might oth-
erwise become blurred in a single target environment. Whereas modular program-
ming often encourages this method of abstraction and isolation, cross-platform
development requires it.
Under this regime, it’s no longer possible to rely on any internal side effects of
the API. Nor is it possible to surreptitiously add an access function, or make a pri-
vate member variable public, because the implementation details—or information
upon which you rely—might not exist on every platform. Consequently, a very
rigid demarcation must exist between the various components.
Cross-platform code is also more stable and more accurate. This is not a gen-
eralization on the people that write it, but as a consequence of it being written. After
all, if your code compiles without warnings on three different compilers, and runs
identically on three different machines, then it is more likely to have been written
solidly. It can be an illuminating experience to compile code under the GNU™ C
Compiler (gcc) when you’re over-familiar with Microsoft™ Visual C++™. Not be-
cause gcc is better, per se, but because it’s different. An unfamiliar set of warnings
can inspire—as well as exasperate.

Teamwork
Most of the games currently available have been written to work cross-platform.
They are usually available on PS2 and Xbox, at least, with many also appearing on
PC and GameCube. Unfortunately for the majority of the industry, this is a new
field, and developers are the only ones solving these problems when the market
goes cross-platform. Marketing can easily add stickers to boxes claiming “PS2 ver-
sion out now. Xbox due Q4.” Publishers only need to snap their wallets shut and
say, “Give us a GameCube version, too, or else” and they can consider their job
over. For developers, however, it represents a significant amount of extra effort.
Most of this extra effort is unknown (or ignored) by everyone else. Of the three
main departments in a development team— the code, the art, and the design—
cross-platform development directly affects all three.
Even when all the individuals within the team have understood (and solved)
the problems involved, the managerial glue that holds them together has other
problems. The producer must decide where to spend the money; for example,
6 Cross-Platform Game Programming

should it be spent on another artist to convert and re-interpret textures, on a new


art tool to convert them automatically, or on hiring a programmer to write a cus-
tom tool. They also need to manage the time devoted to each platform, making sure
the focus is suitable for the product in question: Has a competing product been re-
leased on GameCube that means our game is dated? Has the market changed? Do
we need to consider supporting network play now? And even before the game is
signed and the contracts exchanged, producers must consider how much extra
money is needed to develop each platform, and how hard can they push to drop the
PC version of the game in favor of giving more time over to Xbox, and so on.

Management
One particular management problem that is specific to new cross-platform games
is snobbery. Every console manufacturer believes its machine is the best on the
market. They demonstrate this by releasing their first-party games for their own
consoles alone. So while Nintendo is still building machines, Zelda, Mario, and its
other game licenses are only available for the latest Nintendo platform. This makes
good business sense for Nintendo. The “Exclusively on...” flash on the game pack-
aging nurtures a fan base wanting to play that particular Nintendo game on that
particular Nintendo console. It implies that the game is better tailored to the hard-
ware because there were no other considerations during development. Although
this can limit the range of potential consumers, it can benefit the developers be-
cause it increases the selling power of a game if the console manufacturer helps with
advertising features (which the manufacturer should do, because it helps sell the
console too) and more technical support in times of trouble.
However, wanting a cross-platform release can create bad feelings on the part
of the console manufacturers that weren’t approached first. Because the manufac-
turers hold a monopoly on their console and development kits, they can withhold
materials and support that would otherwise be forthcoming.

Finances
Because most development studios are cash strapped, cross-platform development
can help massage the budget by eliminating the need for excessive hardware. Any
game, including those destined for a single console, can benefit here. After all, if a
game works identically on a PS2 and a PC, then the majority of developers can
spend most of their time working with the PC version, while periodically testing
their work on a shared development kit. Exclusive access to development kits is
usually limited to the lead and senior programmers, the console-specific engine
coders, and those in charge of the control system and technical requirements.1 In
many cases, however, the lead programmer handles these last two tasks. For the
other developers that need access to hardware (such as testers), less expensive kits
Introduction 7

are often available from the console manufacturers that do not support the full
range of debugging facilities, but provide adequate preview features so that the
artists and level designers can view their work in position.
In some cases, sharing hardware presents a double saving because there’s less
software to buy in the form of compilers, profilers, and customized debuggers.
These savings depend on whether your toolset supports a roaming license. If you
haven’t encountered these yet, this simply allows you to install the software any-
where you like, but you can only use it on a limited subset of these machines at any
one time. Shared kit is not a recommended way to build games, but frugal devel-
opers should take note anyway.

Growth
From a human resource management point of view, cross-platform development
can profit the company by helping grow the ability of the team much quicker than
usual. Even junior programmers, often consigned to in-house scripting languages
and menial tasks, will understand the ramifications of the various platforms be-
cause their code will be reused on each of them. So what might initially appear to
them as a simple loop with a “pointer to function” callback, will soon be under-
stood as a potential problem involving cache misses.
In the initial stages of development, instruction of this kind will come from the
senior programmers (and this book), but afterwards, programmers will be able to
use this knowledge themselves to write and fix more involved code. They will also
be able to teach the new junior programmers. This continues to increase the aver-
age ability of the team and cultivate an awareness of the project as a whole. The ju-
nior programmers’ knowledge will become very valuable to the team (and the
company) over the forthcoming years as they graduate to lead, and senior, status.

OVERVIEW OF CROSS-PLATFORM COMPONENTS

The three main development components to a cross-platform project are

The design of the generic, cross-platform, interfaces that handles the various
modules within the game, such as graphics, audio, or input.
The technical, platform-specific, implementation of the low-level driver that
talks to the hardware to bring the interface to life.
The gameplay code that effectively uses these components.

The balance between each section varies significantly according to the module
in question. An input library, for example, has a simple design and implementa-
tion, but the gameplay mechanics that use it are much more complex. The game-
8 Cross-Platform Game Programming

play mechanics will, for example, have to cope with controller configurations, in
which the sidestep might be assigned to the joystick, a button, or a pressure-
sensitive shoulder control.
Software interface design is a big topic, so we’ll limit our discussions to the spe-
cific design patterns suitable for cross-platform game development. This includes
many multi-layered solutions because even though a graphics renderer is consid-
ered the code that “draws stuff,” it’s wise to separate this into multiple components
to deal with specific jobs. In this example, a renderer can be split into two distinct
cases: one component that determines what objects to draw, and a second compo-
nent to draw them. This moves a lot of common engine code away from the low-
level driver, enabling more code to be reused.
The low-level implementation of the driver is the only part of the game that
should interface with the platform-specific API. Even when this API is middleware,
the interface layer should still exist to prevent the game from accessing any com-
ponent directly as this limits the control the engine can exert on the platform. The
more control the engine has, the greater its opportunity for creating faster games
and the less chance the game has for slowing it down.
One additional distinction to make at this point is between platform-specific
code and platform-dependent code. The former indicates code that is intended for
a single platform, but can be compiled and run anywhere. Dependent code, on the
other hand, requires the underlying API or hardware to be present for it to work.
So if we revisit the example of the input library, code that makes a character side-
step left when the PS2 circle button is pressed is platform-specific. However, the
code that actually polled the controller would be platform-dependent.
Within a cross-platform game, often a complex relationship exists between
these two categories because much of the platform-specific code becomes plat-
form-dependent. This is through workflow problems more than technical ones; if
a programmer needs to change a piece of platform-specific code, he is often likely
to solve it with the idea that “It’s only ever on PS2, so I can just call this PS2-
specific function….” In many cases, this isn’t a valid argument. For example, if
you’re converting data assets on the target machine using platform-dependent
code, it becomes very difficult to move that conversion routine offline into the PC-
oriented tool chain at a later date. Also, platform-specific code is only one step away
from the targeted grail of cross-platform code. Dependent code is two steps. A sim-
ple abstraction can often generalize specific code, which means there’s less code to
write, debug, and maintain. This creates a greater amount of commonality between
platforms, and should be the goal for any developer. Throughout the book, the
terms platform-specific and platform-dependent are used in very specific cases.
However, because this can depend on the precise implementation employed, we
tend to err toward the use of platform-specific.
Introduction 9

The Lead Platform


From the start of any cross-platform project, only one question is more important
than “which platforms?” and that is “which platform?” Singular. The lead platform
in any project always takes priority and everyone else must be flexible around this.
Determining the platform is normally a difficult choice because they all have fairly
equal technological plumage. But aside from flame wars, this is a question that
never will be solved by developers arguing the various merits of each platform.
Fortunately, the answer comes from outside the development team, usually from
the publisher. The publisher often dictates a lead platform based on market forces,
the genre of game, or political alliance—although not necessarily in that order. If
the decision has not been made for you, then role-play the position of a publisher
to determine the appropriate focus for your game.

Cross-Generation, Cross-Platform Game Programming


In some cases, a new generation of machines will arrive midway through develop-
ment. This can happen for several reasons, and not necessarily due to bad planning
or elongated schedules on the part of the developers. For instance, a platform might
die unexpectedly early, console launch dates might change, or a new half-breed
console might be released that is worth adopting. This means your development
work might be extended across a wide dynamic range of platforms. Even when
looking at the single-platform PC, there is a large gap between the high-end, mid-
range, and low-end machines. To create a good project on all platforms, you must
take a scalable approach, and adapt the gameplay and resources to match the ma-
chine on a case-by-case, and game-by-game, basis. Programmers for the current
range of mobile phones will have an advantage here because the PDA market is
moving at a very fast and, more importantly, continuous rate. Over the next year,
phones will become as powerful as game consoles. There will be no opportunity to
stop and rewrite your game using a completely different “PDA-only” engine. Each
game will use an evolution of the existing technology, and despite some techniques
being confined to new consoles, the base technology of the game will need to be
cross-generation as well as cross-platform.
During this transition, don’t worry about losing out financially. The PlaySta-
tion 2 sold many millions of units, but for the first few years of its existence, many
games were still written, released, and (more importantly) sold for the original
PlayStation. No one stopped buying PlayStations, or their games, because a better
machine was available. It’s highly unlikely this will change during the next genera-
tion shift, either.
With mid-generational platforms, such as the Sony PSP™, the same cross-
platform approach is needed. Although its heritage is routed in the lore of PlaySta-
tion 2, the scalability argument should win out over the desire to create a PS2-spe-
10 Cross-Platform Game Programming

cific engine that is then tweaked into a PSP engine. Such tweaking inevitably be-
comes a crowbar.

When converting code between two consoles, it’s often easier to port the whole
game to a PC first, and then back onto the new target.

The Theoretical Process


The world of game development is very large and there is no “one size fits all” ap-
proach to any part of the process. Different engines run games of different genres
using different tools with different design philosophies and different styles. At-
tempting to mention all such situations would be a foolhardy exercise. However,
providing game solutions without an example framework is difficult at best, and a
confusing jumble of theoretical retorts at worst. With that in mind, this book will
adopt a theoretical game, tool chain, and environment for its examples.

The Game
The majority of examples within this book have a direct connection with the
process of developing a first-person shooter (FPS). Not because they have any spe-
cial cross-platform qualities, but because the scenarios involving non-player char-
acters (NPCs), explosions, players, and bullets provide a familiar host of good
examples from which we can draw, as most people will have a natural instinct for
the design of at least one FPS without needing any groundwork to be explained.
Naturally, it makes no difference what sort of game you’re writing because the
problems involved in cross-platform game programming are the same within all
genres. Where an FPS doesn’t sensibly support a particular feature or technique,
we’ll indicate a suitable example and include a brief background instead of creating
contrived examples within the example FPS.

The Tool Chain


Game development probably has the heaviest data use of any modern application.
Each frame consists of several megabytes of data, stored as sounds, polygons, and
textures. Getting this data from a raw asset into game memory is one of the con-
tinuing problems in game development.
The start of the process involves an application for creating assets, such as 3ds
max®, Maya®, or Adobe™ Photoshop®. This data is then exported using custom
code to a platform-independent version on disc. From here, the generic data is
converted into custom versions that are optimized for each platform and then built
into disc image files for the various platforms, if required. This is shown in Figure
1.1.
Introduction 11

Object
Viewer
Exporter

Platform Game
Conversion
Metadata
Editor

Disc
Builder

Generic Data Platform-Specific Data

FIGURE 1.1 The cross-platform tool chain.

This is typical of most development houses, and is mirrored by most of the


commercial middleware providers. It is a multi-layered solution that allows each
section of the pipeline to be changed as required, and ensures the minimum mod-
ifications to our platform-specific data.

Although not essential, we have introduced platform-specific image viewers into


our tool chain that help improve the turn-around time because they are less bulky
than a complete game engine.

This conversion process is consequently written as two halves; you have half of
a converter that adapts an image file into generic raw data, and another half to build
a platform-specific asset from the generic resource. Splitting the conversion rou-
tines into two makes it easier to cross onto new platforms, such as Xenon®, because
you only need to add the missing half.
When building assets for a cross-platform pipeline, you need to make a few
considerations over and above that of a single-platform game. We’ll look at these
considerations in Chapter 2.
12 Cross-Platform Game Programming

The Engine
The engine running your game has the greatest scope for variation. Trying to pre-
dict every breed of engine is impossible. All we’ll assume is that you have some form
of code to process the game objects, each derived from a common base class, and a
means for their inter-communication. Throughout the text, we’ll refer to this as an
event system, or message passing system, depending on context. These messages are
assumed to arrive instantaneously.
Any API calls not described within these pages, and all classes referred to, are
similarly theoretical and are assumed to fulfill any basic functionality ascribed to
them. The implementation will conform to the rules of cross-platform develop-
ment (as laid out in Chapter 2), but won’t be described in detail unless a new idea
or concept needs to be presented.

THE DEVELOPMENT PROCESS

The physical act of developing code has been discussed many times. When applied
to cross-platform development, however, this role changes.

Code Is Code
Writing cross-platform code is somewhat different from writing standards-
compliant code, although the two are not mutually exclusive. Indeed, to write any-
thing that is cross-platform without adhering to standards would be the gentle
equivalent of changing the preprocessor macro of TRUE to 0, or PI to 3. It would be
more true to say that cross-platform code is like writing to standards on steroids.
You have to make sure that the compiler cannot misinterpret any line of code, that
it says exactly what you mean, and that you mean exactly what you say. Running
the code through checkers such as Lint can be very useful here, as can adopting peer
reviews, and compiling with stringent warning settings on alternate compilers.
More complications occur because of buggy compilers, in which certain lan-
guage constructs cause incorrect code to be generated or fail to build entirely.
Granted, this is not as common now as it has been in the past, but it still happens.
There are also places where the C standard states that the behavior of certain code
is “undefined.” Although the compiler might be standards compliant, the three lit-
tle words of “undefined,” “undetermined,” and “unknown” indicate that each
compiler is at liberty to process your code in any way it sees fit. The classic interview
question of “what result does a = a++; give” is a prime example, and should nat-
urally be avoided. This is just one of many similar examples throughout the book.
Chapter 2 highlights some of them, but during the course of development, you’ll
discover your own favorites.
Introduction 13

Standards-compliant code, however, is only half the story. The typical scenario
of a present day developer reveals the other half. Consider for a moment this set up:

“The developer will be experienced with Microsoft Visual C++ or .NET™, run-
ning under Windows 2000™ using the Win32™ API on an Intel machine. The
developer’s PC will have a 128-channel sound card (as standard), a 256-MB
graphics card, a large hard drive (containing an equally large swap file), 2 GB
of RAM and a 19-inch monitor.”

How much of this seems familiar? Most of it, no doubt. This is not an atypical
environment, as the development tools required to build and play modern games
require this amount of processing grunt. In cross-platform games development,
everything presented in that scenario is so far wide of the goal posts, it’s not even in
the same stadium.
Most PC programmers can become spoiled by being able to write clever algo-
rithms that use a lot of memory, are very compute-intensive, or both. They can also
get used to the safety net of a swap file, and never check their memory allocation
function returns safely. On a console, memory can (and sometimes does) run out,
so you still need to keep the game running, even though some particular feature
cannot be allocated. Not only that, with each console having a different amount of
memory (and the game resources using a different memory footprint), you might
run out of memory during different parts of the game on the various consoles. You
need to cope with that, too. And, if you’re developing without a console develop-
ment kit, how do you determine the effect of your code on the real hardware?
A further consideration stems from the fact that Microsoft Developer Studio™
is not the only environment. It compiles code differently from other compilers (in-
cluding .Net), with different resultant code and different warnings and error mes-
sages. Furthermore, the Win32 API is, obviously, not available on the PS2 or
GameCube, and only partially implemented on the Xbox. So, anyone who’s used to
OpenFile should get used to something else.
Another important, but also less obvious problem in this scenario, is the fact
that the byte order of the data on a GameCube is different from the PC. This is
known as endian-ness and makes it more difficult to load binary data (such as
graphical texture images) into memory. A number saved as 0x12345678 on the PC
(which is Little Endian) appears as 0x78563412 when loaded into a GameCube (a
Big Endian machine). Although the endian-ness of a number is of no concern while
it remains within memory, as soon as it is transferred to or from disk, the data
needs to be converted.
Finally, those working on the console-side of cross-platform development
don’t even have the luxury of a monitor to preview their work. Consoles have tele-
vision sockets. That means low resolution (usually a 480 horizontal line maxi-
14 Cross-Platform Game Programming

mum), color bleed, and brightness and contrast settings that can (and will) vary ex-
tensively between make, model, and age of the TV. Although the visuals are nor-
mally a problem assigned to artists, the inability to display more than a few lines of
debugging text onscreen can be prohibitive for the programmer.

Console Limitations
When working on the PC platform (under Windows, Linux™, or BSD™), you have
remarkably few limitations. If the game runs too slowly, buy a faster processor. If
the graphics aren’t good enough, add more polygons, increase the texture sizes, and
upgrade the graphics card. If you can only play five gunshot noises at once, replace
the sound card. In some cases, you can even just postpone the game for six months
until the entry-level PC hits a suitable specification to show off your game at its
best.
Unfortunately, console programmers have none of these benefits. The console
machine you have now is the only version of the machine you need to consider be-
cause it cannot be upgraded2 with more RAM, a different graphics card, or a faster
processor. There’s no swap file to fall back on if memory gets tight or easy upgrade
path to cover hardware bugs. Although these problems are not unique to cross-
platform development, their effect multiplies when you have to simultaneously
consider these effects on different machines. For example:

The memory footprint for the level data might be 12 MB, 20 MB, or 40 MB.
The same code might compile to 4 MB, 6 MB, or 12 MB.
The graphics engine might be bound by fill rate on one platform, and compu-
tation on another.
The CPU might be fast enough to process all the Artificial Intelligence (AI) in
one frame, or it might not.
Any number of other equivalent problems can also occur.

Each console is a finely balanced machine. If it’s lacking in one area, another
area is usually super-charged to compensate. This ensures that each console, when
considered on its own merits, is roughly as good as its competitors. When the same
game needs to run across all platforms, you have to either look for ways to scale
back certain features (perhaps the AI will only think every other frame), or build
everything to run on the lowest common denominator and pad out the game with
bonus code in each particular area where the console is under-used.
Several methods for tackling this problem are covered later in the book. No
matter which method is used, programmers (along with artists and designers)
need to take the initiative, consider the limitations, agree to the confines, and stick
to them.
Introduction 15

The Processor(s)
The processor(s) will always be fixed, but you need to take into account whether
there is one large behemoth CPU that controls everything, or if the work needs to
be split between a lot of smaller, slower chips.
Working with a single CPU means that every game feature will (more than
likely) run in sequence. So if the AI takes a little longer to process, the graphics en-
gine can compensate by using a lower level of detail when rendering the meshes. In
contrast, having separate CPUs running in parallel means the game can only be as
fast as the slowest process. If this is the AI (for example), how does it react if more
enemy characters are being processed? To use the vernacular, does it scale?

Disk Access
Disk access has two main variables: speed and size. If the disk is very slow (in com-
bined terms of latency and transfer rate), but the processor is fast, then it’s a fairly
simple process to store all the data on the disk in a compressed format, and de-
compress it while it’s being read. Conversely, the opposite may be true. Addition-
ally, the disk size might be small (having to reside on a 650-MB CD-ROM, instead
of a 4.7-GB DVD), necessitating the need for compression, but the processor will
then require a larger memory buffer to handle the decompression within a reason-
able time frame. As we said before, this problem may exist on any of the consoles,
but the method for handling it in each specific case will vary depending on the plat-
form. This in turn will have an impact on the tool chain, and the way in which
artists create their work.

Libraries
One beneficial facet of cross-platform development is the ability to use stan-
dard libraries. These might be Open Standards (with a capital “O”) such as
OpenGL or Simple Directmedia Layer (SDL), closed ones such as RenderWare® or
Gamebryo®, or internal ones developed by the in-house technology team or senior
developers. Each library allows multiple platforms to be serviced directly through a
common API, abstracting the hardware—and operating system-specific—details
away from the game code.
Employing such a library prevents you from having to reinvent a lot of wheels,
and there are many examples on the Web of OpenGL code that’s been written for
Unix®, but works flawlessly on Windows, and vice versa. A few years ago, a com-
pany called Loki Entertainment ported Windows games to Linux by modifying ex-
isting DirectX® code to use the SDL API instead. In both of these cases, the
common interface between platforms helped speed up development.
A common API is essential in a cross-platform engine; but it isn’t the only re-
quirement for a cross-platform project. After all, a computer game is more than just
16 Cross-Platform Game Programming

its engine, the engine is not just the graphics code, and the graphics code is not de-
fined by its capability to push polygons. The following paragraph will tackle these
issues in order.
The game engine needs to consider how to access the disk and allocate mem-
ory. These simple tasks take on a new complexity in our world. The sample code for
an OpenGL application might read a text file using the fopen function, for example.
This is part of the C standard library, and not guaranteed to exist on a games con-
sole. Even when it does exist on the consoles for which you’re currently developing,
the function must exist on all of them to be used effectively. Will your publisher
come back after a year and say “It’s going well, here’s some cash, just do another
port?” If so, every instance of fopen will have to be retroactively replaced. Further-
more, fopen is a blocking function, which means it doesn’t exit until it has com-
pleted its task. In a single threaded environment, this means the whole machine
cannot do anything until the file has been opened. If the disk cover is open or the
CD-ROM has been removed, you won’t be able to access the file, and because the
program has been suspended, you won’t be able to print a message onto the screen
saying “Please put the disc back in” either. On its own, the standard library isn’t
powerful enough. It was never intended to be. So we either need to create an ab-
straction layer for the filesystem to hide our use of nonstandard library calls, or
make sure we’re always using threads. In reality, we’ll use an abstracted filesystem
anyway because it provides other benefits. We’ll also often employ an abstracted
thread library because the most common threading library, pthreads, is not avail-
able on consoles since they exist within a different set of standards. Not only that,
but after you have abstracted the basic filesystem, you need to handle the different
conventions for filenames. Windows uses names that appear as, c:\projects\
game\mymesh, whereas Linux might use /home/steev/game/mymesh. Furthermore, file-
names might be case sensitive or limited to a certain number of characters. All
these possibilities need to be considered.
In the same vein, the graphics code is not just about drawing the polygons. The
polygonal mesh data needs to come from somewhere, so most sample code or mag-
azine articles include a list of vertices in an array, hard-coded into the source. In the
real world, this cannot work because the amount of game data easily outstrips avail-
able memory. Instead, you need to write a data-driven component that loads arbi-
trary data from an external package and prepares it for the graphics code. This
again uses the abstracted filesystem, but it also uses platform-specific code to set up
the graphics chip correctly. In addition, we’ll also need some extra cross-platform
resourcing code that allows the game to reference these (platform-specific) poly-
gons from our (common) code, because we must be able to say “draw this object in
this position.”
In theory, you only need a single rendering function to write a 3D graphics en-
gine—DrawOnePolygon—but the overhead of sending each polygon individually to
Introduction 17

the hardware is prohibitively expensive. Instead, each hardware API will have its
own method for storing and referencing groups of polygonal data that has no rele-
vance to the outside world, or any other API. This platform-specific data then needs
to be manipulated in a cross-platform manner for tasks such as collision, move-
ment, and animation. This often requires a duplicate set of structures for each of
render data and collision data. This apparent waste will pay for itself very quickly,
however, with the increased ease by which all platforms can optimize their specific
half of the equation without intruding on the other half.

ABOUT THE BOOK

I
n attempting to deliver as much information as possible, code explanations are
kept to a minimum, all utilizing the same rules and guidelines as follows.

Coding Style
Throughout the text, code samples are given either in their entirety or in frag-
ments. They have been taken from the author’s own engine and chosen to illustrate
the points within the text. The naming conventions used within the code are:

sgxInitialCaps: A global function, datatype, or enumeration ready for cross-


platform work, meaning it could be used on any platform without problems. It
may present an abstraction with platform-dependent code underneath, or a
completely generic function.
SGX_UPPERCASE: A macro, ready for cross-platform work.

OS_ANY_CASE: A pseudo-function indicating OS-specific functionality. The


name is not intended to reflect any existing function, merely present the role of
an equivalent routine within the API.
PS2_ANY_CASE: A pseudo-function indicating PS2-specific functionality. Again,
the name does not reflect any existing PS2 function. This is used to distinguish
between a generic “any OS” code, and specifics.
XBOX_ANY_CASE: As above.

GC_ANY_CASE: You get the idea.

We’ve chosen this naming convention for two reasons. First, and most obvi-
ously, it highlights the cross-platform abstractions that exist within the function
and reminds us of the task at hand. Second, by including uppercase letters in the
18 Cross-Platform Game Programming

name, it cannot conflict with any of the standard C types, functions, or other third-
party library’s features.
Several functions and classes are also prefixed with letters such as PS2, Xbox, or
GC. Again, these are meant to illustrate examples, and no connection with the ac-
tual platform or its API should be inferred.

NON-DISCLOSURE AGREEMENTS

There have been many dissenting voices about the use of NDAs, with them being
called “the scourge of our industry” and “monopolistic.” Many find it strange that
a scientific discipline such as computing should hide behind this cloak, allowing us
to stand only on the shoulders of proverbial giants in our local vicinity. But there is
nothing we can do about this. All consoles have an NDA, and we must abide by it.
To that end, we cannot, and will not, reveal any secrets about the APIs for PlaySta-
tion 2, Xbox, or GameCube. Nor will there be any named functions, macros, or
magic numbers. All the information presented in this book, including the machine
specifications shown in the appendixes, has been gleaned from magazines, press
packs, clean room engineering projects, and numerous Web sites around the world.
These appendixes have been presented separately because a side-by-side compari-
son is both unfair and nonrepresentative. After all, the clock speed of the G5™ and
Intel processors do not reflect their relative power. Where a direct comparison is
not possible or the information is under NDA (or could not be ascertained from a
public source), the entry is left blank.
Any time the workings of a platform need to be explained, imaginary stub
functions will be invented to process the theoretical data, and return theoretical re-
sults. There is no connection, intentional or otherwise, between the name used
here and that of the official version. Wherever possible, samples will use openly
published APIs such as OpenGL and DirectX.

NOTES TO THE READER

All the examples given within the text are correct at the time of going to press.
However, tools change, compilers are updated, libraries are patched, and new bugs
are added. It is entirely possible that a particular example might fail to work in ex-
actly the same manner as given here. That’s life. This doesn’t negate the point itself,
but reiterates it. Along with the fundamental rules of test, test, and test again. The
principle arguments are exactly the same.
Introduction 19

ENDNOTES

1. All consoles have a list of requirements that the game must fulfill to be
approved by the manufacturer before release. These lists vary between con-
soles, and are private. It dictates criteria such as maximum load time and
the wording for various error messages.
2. Even when the console does support upgrades (such as with broadband
adapters), you still need to work toward the lowest common denominator;
that is, a machine without upgrades.
This page intentionally left blank
2 Top Ten Tips

In This Chapter
Abstraction
Commonality
Limitations
Modularization
Resource Creation Path
Granularity
Separation and Isolation
Debugging and Profiling
Predictability
Turn-Around

THE BASIC ISSUES

Cross-platform development is an issue that affects a game’s entire code base. The
graphics and audio programmers aren’t the only ones that have a job to do. All pro-
grammers working on the game need to always remember that their code will be
compiled, run, and very often debugged on platforms other than the one on which
it was originally written and tested. This might seem obvious, but it’s frequently
overlooked. What difference does it make anyway? Why isn’t it enough to use the
C language?
To explain this, we offer a number of fundamental ideas that need to be ad-
hered to across all code within the cross-platform environment. With so many dif-
ferences between platforms, we need to know how to consider, cover up, or isolate
those differences. Each idea is supplemented with code samples, demonstrating

21
22 Cross-Platform Game Programming

where the methods can be applied. The methods can be applied elsewhere as well;
example-ridden references to the filesystem will contain ideas that are just as
applicable to the audio code, input library, or network code.

ABSTRACTION

If this book were condensed into a single paragraph, line, or word, the word
Abstraction would be on the short list of words to use. It is the cornerstone of every-
thing we do. Abstraction means to generalize, ignoring details and specifics. For
programmers, it’s being able to write code without being concerned about the
hardware, and knowing in advance that the behavior of every platform will be iden-
tical—not similar, but identical. Everything you do needs to be abstracted in some
way and at some level. Even the code you write, although it’s all C, is just an ab-
straction. It abstracts the low-level machine code away, allowing you to write a
more general program. When you declare an integer variable, for instance, you’re
abstracting a datatype. When you read from a file, you’re abstracting the filesystem,
and so on. Some abstractions are simple, consisting of nothing more than a well
placed #define or typedef in a header file. Sometimes they are more complex,
where one function hides a wealth of code behind a simple nomenclature, such as
PlayThemeMusic.
What matters is that when you abstract something, no side effects are intro-
duced in the process. For example, the standard library function qsort hides the
basic implementation details from you, but it doesn’t behave identically on all plat-
forms because each compiler will provide its own implementation of qsort. Be-
cause the language specification isn’t strict enough to prevent side effects, qsort
only has to perform a sort, not necessarily a quicksort. An example of this difference
can be seen if the qsort function is required to sort a list containing two identical
primary keys. In that case, the algorithm (not the qsort callback function) is re-
sponsible for the list’s final order. The strict requirements placed on cross-platform
development mean that functions with side effects are unacceptable.
So what needs to be abstracted?

Game: Should be programmed in a generic manner, using only the abstractions


provided by the engine.
Engine: Although parts will be platform specific (for example, graphics driver),
the majority of code (such as geometry calculations) should be common. The
interface that the engine presents to the rest of world must therefore be com-
mon, too.
Top Ten Tips 23

Everything Else: You should use nothing that is compiler-specific or platform-


specific. This includes memory management routines and datatypes.

Also, do not be afraid to consider multilayered abstractions. They are both


necessary and useful. The best example in this category is the filesystem.
At one level, C’s standard library has provided a layer of abstraction for you
with the fopen, fread, and fclose functions; however, they are, for most purposes,
limited and only cover the basic file-handling capabilities. They are so basic, in
fact, that some platforms do not consider it worthwhile to include them in the
standard libraries. We’ll most likely need a series of wrapper functions that use the
platform-specific versions, such as OpenFile, to provide the much needed features.
On top of these wrapped functions, we’ll then produce another layer of abstraction
that allows us to access different types of files, such as a memory card file or a sin-
gle file within a .ZIP package, as if they were identical. The latter becomes impor-
tant on the PlayStation 2 where a strict ISO 9660 standard is applied, and we need
to overcome the limit of 30 files in a directory as seen in Chapter 5, “Storage.”
If you are using a third-party library or middleware solution, you should ab-
stract large portions of it too. At the very least, abstract the input library, the de-
bugging helper routines, and the memory allocation code. Even if you call the same
function with the same parameters, wrapper it with your own code. This will make
it easier to add debugging code around the API calls and quicker to determine
whether the parameters for a specific function call are valid. This is especially use-
ful when the third-party function is called from several places, and you have no li-
brary source on which to place a breakpoint. Additionally, wrapping these
functions will even make life a little simpler if you change middleware products
during development. Although if you do need to change middleware solution dur-
ing development, this is probably the least of your problems.
Abstracting middleware also helps if your adopted solution doesn’t support a
platform that later becomes a requirement. This might be a new platform that be-
comes available due to an extended deadline, or an old platform that gains a resur-
gence of interest due to a change in the publisher’s allegiance. Although abstracting
middleware doesn’t make the task of writing a new engine any easier, it does give
you an idea of how many middleware functions need to be replaced, which lets you
judge a more realistic timeline.
So much of cross-platform development involves abstractions that it should
become second nature after a while. Much of this book gives full examples on how
to abstract various components at the game, engine, and system level.
24 Cross-Platform Game Programming

COMMONALITY

Commonality follows on directly from the discussion of abstraction. When ab-


stracting part of the engine (for example, the renderer), consider carefully which
components are truly platform-specific, and which can be made common across all
platforms. The render component might be comprised of code to determine which
areas of the level are visible (through a portal system or potentially visible set) and
separate code to send this list of textured polygons to the graphics chip. The first
step in this pipeline is cross-platform. The second is not. This commonality needs
to be determined to build a mutual, stable, base.
These interfaces extend across every minutia in the project. At one end of the
scale, you must ensure that the size of every datatype is common to all platforms,
even if the structures they build are not. This (as we shall see in Chapter 3, “Mem-
ory”) means that the standard types, such as short, int, and long must not be used
and should be replaced with tUINT16 and tINT32, for example.
At the other end of the scale, the graphics engine API should implement com-
mon functions, for example, DrawWorld, which is implemented once and available
for all platforms, and the platform-specific DrawWorldMesh function that it calls. Fol-
lowers of design patterns will recognize this as something similar to a bridge. Fur-
thermore, if a function inside one driver needs to change a global state within the
engine, the function should reset that state before it exits to remove any side effects
and maintain commonality. This topic is explored further in the “Granularity” sec-
tion later in this chapter.

LIMITATIONS

Every part of the game development process involves limitations that you must
overcome. A cross-platform game has more limitations than most, and extends be-
yond the usual questions about polygon counts. You also need to consider the lan-
guage, compiler, and its libraries.

Language Limitations
The first limitation to overcome is the language. If we succumb to these limitations,
we can’t even compile our game, let alone run it to the point of exhaustion. The
language in question is probably C or C++, so we must focus our attention on the
minutiae of C—namely, standard C.
A programming language is usually learned by example. We copy the code
samples in our book of choice, change them, add to them, delete bits from them,
and make them our own. As time goes by, we collect more examples. Rarely do we
Top Ten Tips 25

look behind the scenes of a language to find out what makes it tick and why the ex-
amples work the way they do. When a lot of our work is in a single environment
(perhaps the PC—usually under Microsoft Windows, but more frequently under
Linux), we adapt our coding style to the compiler and platform we are using (often
subconsciously). This might include involuntary use of vendor-specific functions
that appear in the so-called standard libraries (such as _gvct, or stricmp), compiler-
specific extensions (such as the <? operator), or special datatypes (such as qword). In
extreme cases, you might be tempted to write code for a specific compiler to gain
extra speed. It’s imperative that every line of code written for a cross-platform pro-
ject is completely standard to ensure that the code cannot be misinterpreted in any
way, by any compiler.
To illustrate this point, consider these questions concerning language.

Language Questions:
1. How many bytes constitute a long variable?
2. Is a char signed or unsigned, by default?
3. What is the value of a after this code?
int a = 1;
a = a++;
4. What is the value of sizeof(‘a’)?
5. In which directory does the header file live, given the following code?
#include “graphics.h”

Language Answers:
1. Depends on the platform. Usually 4 bytes on a 32-bit machine, but it’s 8 on
the PlayStation 2.
2. Depends on the compiler. You must explicitly state signed or unsigned
when using chars. All font code, for example, should use an unsigned char
to cope with accented characters. Games using Unicode will use their own
(nonchar oriented) datatype.
3. Depends on the compiler. The expression is undefined because the value of
a is changed twice before the sequence point (that is, the semicolon, in this
example). It could be 1 or 2, or, in really perverse compilers, 934537.
4. Depends on the language. If it’s compiling as C, it will be compiler-
dependent, and its result will be identical to sizeof(int). When compiled a
as C++, it will report 1 byte.
5. Depends on the compiler. The double quotes usually mean current direc-
tory, but if used within a header file, the compiler might interpret this as
the directory of the current header file, or the source file where the com-
piler started building. This makes it inadvisable to nest headers in different
directories, although in practice this is difficult to avoid.
26 Cross-Platform Game Programming

As you can see, building the code to see what the compiler does is not good
enough because you’ll ultimately be building the game with more than one com-
piler. Cross-platform programming requires a deeper understanding of the lan-
guage. The only way you can acquire this knowledge is by reading. Your first stop
should be comp.lang.c newsgroup’s excellent FAQ at http://www.faqs.org/faqs/C
faq/faq/index.html. This FAQ contains many good questions and answers concern-
ing how to handle several tricky constructs. Should the phrase “not portably” ap-
pear in the answer, avoid using it, even if it appears to work on your current set of
compilers.
For a more definitive, but slightly drier, coverage of the language, the best doc-
ument to read is the ANSI® standard itself. The ANSI standard is a big, and occa-
sionally unwieldy, document that describes every facet of the C language, and what
each compiler must implement to be considered “ANSI-compliant.” Any compe-
tent programmer can understand most (if not all) of this document. Experienced
programmers with a good working grasp of the language can avoid this step.
The completed ANSI/ISO® standard is not free,1 although the final draft can be
downloaded from the Internet. Some choose to purchase the much less expensive
book entitled The Annotated ANSI C Standard instead;2 although its annotations
are sometimes wrong or misguided. It is, however, an inexpensive way to get the
majority of the standard, but keep in mind that not all of the standard is included.
This might appear like a lot to read, but it’s easier to learn what is legal (and
apply only that knowledge), than it is to learn every extension on every platform
and explicitly avoid them. After all, the legal features constitute a finite set. How-
ever, it is possible to make an educated guess as to what is nonstandard. For in-
stance, any function or macro featuring one or more underscores is probably an
extension (size_t is one notable exception). Those that begin with an underscore
are almost certainly extensions. Any function name in MixedCapitals is probably an
extension, too. This is a sign of Hungarian Notation, which originated from Charles
Simonyi at Microsoft.
In contrast, names that are comprised solely of lowercase alphabetic characters
are likely to be standard, unless they’re the typical gotchas, such as stricmp. If in
doubt, look for the prototype in the header files. It’s very likely such names will be
sandwiched between #ifndef __STRICT_ANSI macros, or similar. The MSDN® has
extensive (and very good) documentation on the standard library. Under .NET,
pressing #F1 on any library function opens the appropriate help page for you and
states whether the function is a Microsoft extension.
As always, prevention is better than cure. Most compilers provide a way to
switch off these extensions, either through a dialog box or a macro that must be de-
fined before including any standard header files. Depending on the compiler, this
can be more trouble than it’s worth because each platform likely needs these exten-
sions to pack structures correctly, or to use specific datatypes that access and con-
Top Ten Tips 27

trol the hardware. With careful modularization, you can limit these occurrences
and compile the game under a strict ANSI compiler.
Although we have concentrated on C here, the same ideas apply to C++.
There’s just more scope in C++ for problems. For example, the construction order
of globally instantiated classes is not fixed, so any interdependencies will not behave
portably (we’ll cover this in Chapter 11, “The Bits We Forget About”). Fortunately
for the game programmer, after the basic architecture has been completed, any
new functions only use a small, well-known subset of C++, such as references, tem-
plates, and the standard template library (STL).

Some of the more complex templating techniques will not work under some com-
pilers. One typical example is partial template specialization, which fails under
Microsoft Visual C++ 6.0.

Library Limitations
For any C compiler to be ANSI-compliant, it must have a set of standard libraries.
C++ also includes the standard template library (STL). All of these are standard,
tested components that can be used without fear in a gaming environment. Unfor-
tunately, a cross-platform gaming environment might raise problems because the
implementation might differ slightly between compilers, as you’ve already seen
with the qsort function.
STL implementations also differ between platforms. Even the versions on PC
and Xbox (despite their heritage) are different from each other. If you are using STL
out-of-the-box for basic single platform work, then the default implementation is
usually good enough because it behaves well enough for end users to consider it
identical to anything they’ve used before.
On the other hand, if you use your own memory management code, you might
need to work around specific issues in STL. The amount of work will increase as ef-
fort is duplicated across each specific implementation and each platform. In these
situations, you might decide to ignore your vendor’s implementation, and use a set
of third-party libraries, such as STLPort (http://www.stlport.org), or those provided by
Boost (http://www.boost.org). This is a case when reinventing the wheel is a good
thing. Only here, someone else has done the reinventing for you. You just need to
test it.

Compiler Limitations
We rarely need to consider compiler limitations because the compiler’s sole job is
to implement the language standard, and we only practice our art according to that
standard. However, you should consider four issues about compiler limitations.
28 Cross-Platform Game Programming

Standard Interpretations
Standards are good, but there are so many to choose from. Although a compiler can
adhere to the letter of the law, it doesn’t necessarily behave according to the spirit.
This might be due to bugs in the compiler, extensions that cannot be switched off,
or undefined behavior that is permitted by the standard. However, before your
project ships, you’ll find at least one really annoying problem that exists between
compilers: variable scope in C++, for example.

for (int i=0;i<10;i++)


{
// ... do stuff ...
}

The loop counter i exists only between the braces because that is its scope. It in-
crements from 0 to 9, and forces the loop to exit when it reaches 10. This is true of
every compiler.
When the loop terminates at 10, i goes out of scope and it is destroyed. This is
not true of every compiler. Some compilers do not destroy i, allowing it to be used
in another loop later on in the function. This causes problems when another loop
in the same function declares i again—perhaps in another for loop. This produces
a “redeclaration of i” error on some compilers. If the declaration is removed, then
every other compiler will complain that i hasn’t been declared. The solution is
simply to move the declaration outside the for loop.

Under Visual C++, this error can be avoided by using the Disable Language Ex-
tensions option; however, this can cause more problems than it solves because some
of the official header files are not compliant. .NET 2003 does not suffer this prob-
lem because a better option is available in the form of /Zc:forScope.

Creating these workarounds is a nuisance, but that’s par for the course with
cross-platform development. To stop other developers from falling into the same
traps, you should create a small document of these differences, and keep it in your
source control tool. If you work with code reviews, reference that document as
part of your process.

Abstracting Compiler-Specific Features


Each compiler has three separate categories of macros and extensions. First, some
are part of the C standard, such as __FILE__ to indicate the current file, and
__LINE__ for the current line number in the source. Both of these will find a use
when we look at memory allocation in Chapter 3, “Memory” and Chapter 6, “De-
bugging.” These are language features, so we don’t need to worry about them.
Top Ten Tips 29

Next are the features that exist in all compilers, but in different forms. For ex-
ample, to distinguish between a release and debug build of the game, the compiler
often predefines a special symbol. A debug build might be indicated with any of the
following:

DEBUG
NRELEASE
_DEBUG
__DEBUG
DEBUG_BUILD

The vendor could also use any other macro it deems appropriate. These macros
could be declared with either

#define DEBUG

or

#define DEBUG 1

Because each platform requires a different compiler, we can’t rely on any par-
ticular standard and so must create a separate header file for each platform-
compiler combination like this:

// For the CodeWarrior compiler, running on a Nintendo GameCube


#ifdef DEBUG
#define SGX_DEBUG_BUILD 1
#undef SGX_RELEASE_BUILD
#endif

The implementation then requires

#if SGX_DEBUG_BUILD
#endif

to be placed around cross-platform, debug-only code. This method is favored be-


cause it’s possible to upgrade an #if to #ifdef (using the preprocessor function, de-
fined), whereas you cannot change an #ifdef to an #if.
The third subcategory of compiler specifics are those that hide in #pragma state-
ments, or are extensions, usually prefixed with one or two underscores. For games
programmers, the most often used directives are __inline and __force_inline.
Exploring the Variety of Random
Documents with Different Content
The Project Gutenberg eBook of Wolf Ear the Indian:
A story of the great uprising of 1890-91
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.

Title: Wolf Ear the Indian: A story of the great uprising of 1890-91

Author: Edward Sylvester Ellis

Illustrator: Alfred Pearse

Release date: November 5, 2019 [eBook #60633]

Language: English

Credits: Produced by Al Haines

*** START OF THE PROJECT GUTENBERG EBOOK WOLF EAR THE


INDIAN: A STORY OF THE GREAT UPRISING OF 1890-91 ***
Cover art

WOLF EAR THE INDIAN


A STORY OF THE GREAT
UPRISING OF 1890-91
BY

EDWARD S. ELLIS
Author of "Captured by Indians," "A Hunt on Snow Shoes,"
"The Mountain Star," etc. etc.

WITH FOUR FULL-PAGE ILLUSTRATIONS BY


ALFRED PEARSE

SEVENTEENTH THOUSAND
CASSELL AND COMPANY, LIMITED
London, New York, Toronto and Melbourne

ALL RIGHTS RESERVED

CONTENTS
CHAPTER I.
"The bullet had passed startlingly near him"

CHAPTER II.
"He's up to some mischief, I'll warrant"

CHAPTER III.
"There are fifty hostiles"

CHAPTER IV.
"We are enemies"

CHAPTER V.
"What will be their next step?"

CHAPTER VI.
"Ay, where were they?"
CHAPTER VII.
"It came like one of them Kansan cyclones"

CHAPTER VIII.
"The bucks were coming up alarmingly fast"

CHAPTER IX.
"He has made his last scout"

CHAPTER X.
"Oh, there is Wolf Ear?"

CHAPTER XI.
"I'm off! Good-bye!"

CHAPTER XII.
What happened to Wolf Ear

LIST OF ILLUSTRATIONS
"I'm off! Good-bye!" ... Frontispiece

"The figure of a Sioux Buck"

"Hurrah!"

"Oh, there is Wolf Ear!"

[Transcriber's note: the first three illustrations were missing from the source
book.]
WOLF EAR THE INDIAN

CHAPTER I.

"THE BULLET HAD PASSED STARTLINGLY


NEAR HIM."

Before relating to my young friends the incidents which follow, I think a


few words of explanation will help them.

Perhaps some of you share the general mistake that the American Indians
are dying out. This is not the fact. There are to-day more red men in the
United States than ever before. In number, they exceed a quarter of a
million, and though they do not increase as fast as the whites, still they are
increasing.

It is true that a great many tribes have disappeared, while others that
were once numerous and powerful have dwindled to a few hundreds; but on
the other hand, tribes that were hardly known a century ago now include
thousands.

The many wars between the United States and the Indians have been
caused, almost without exception, by gross injustice towards the red men.
They have been wronged in every way, until in their rage they turned
against their oppressors. The sad fact at such times is that the ones who
have used them so ill generally escape harm, while the innocent suffer. The
Indian reasons that it is the white race that has wronged him, so he does
them all the injury he can, without caring whether the one whom he slays
has had a hand in his own persecution.
The Indian, like all savages, is very superstitious. He loves to think over
the time, hundreds of years ago, when the red men roamed over the whole
continent from ocean to ocean. He dreams of those days, and believes they
will again return—that the pale faces will be driven into the sea, and the
vast land become the hunting ground of the Indians.

Some years ago this strange faith took a wonderfully strong hold upon
those people. The belief spread that a Messiah was coming in the spring of
1891, who would destroy the pale faces and give all the country back to the
red men. They began holding wild dances, at which the dancers took hold
of hands and leaped and shouted and circled round and round until they
dropped to the ground, senseless and almost dead. These "ghost dances," as
they were called, were carried on to please the new Messiah. When the
dancers recovered, they told strange stories of having visited the other
world. All who listened believed them.

The craze spread like wildfire, and before the Government understood
what was going on, the Indians were making ready for war. They were well
armed, eager to attack the whites. The principal tribe was the Dakota or
Sioux, the most powerful on the American continent.

The leading chief or medicine man was Sitting Bull. He was a bad man
who had made trouble for more than twenty years. He could not endure the
white men, and, when not actively engaged against them, was thinking out
some scheme of evil.

As soon as the new Messiah craze broke out, he turned it to account. He


sent his friends among the tribes and urged them to unite in a general war
against the whites. The officers and soldiers were very patient, and did their
best to soothe the red men, but matters grew worse and worse. Trouble was
sure to come if Sitting Bull were allowed to keep up his mischievous work.

So it was decided to arrest him. In the attempt several people were


killed, among them Sitting Bull himself. Danger still threatened, and many
believed that it would require a great battle to subdue the Indians.

Now, if you will look at your map of the United States, you will notice
that the Missouri River runs across the middle of the new State of South
Dakota. On the southern boundary of the State, a large tract of land,
reaching one-third of the way westward to Wyoming, and with the White
River forming in a general way the northern boundary, makes what is
known as an Indian reservation.

There are many of these in the West. They belong to the Indians, and the
Government has an agency at each, to see that no white people intrude. The
Indians are forbidden to leave these reservations without obtaining
permission, and at the agencies they receive the annuities or supplies paid to
them by the United States Government for the lands elsewhere which they
have given up.

Half of the reservation directly west of the Missouri is the Rosebud


Agency, and the other half the Pine Ridge Agency. It was at the latter that
the grave trouble threatened.

When the discontent was so general, the danger extended hundreds of


miles north and west. That section is thinly settled, and the pioneers were in
great peril. Most of them hurried to the nearest forts for safety, while others
waited, hoping the cloud would soon pass by.

If your map of South Dakota is a complete one, it will show you a small
stream to the westward of Pine Ridge, named Raccoon Creek, a tributary of
Cherry Creek, itself a branch of the Big Cheyenne River.

At the time of the troubles, the Kingsland family, consisting of Hugh, a


man in middle life, his wife Molly, his daughter Edith, eight years old, and
his son Brinton, a little more than double her age, were living on Raccoon
Creek.

The family had emigrated thither three years before from Kansas, and all
would have gone well in their new home, but for the illness of Mr.
Kingsland.

Something in the climate disagreed with him, though the rest of the
family throve. He was first brought low with chills and fever, which after
several months' obstinate fight finally left him weak and dispirited. Then,
when he was fairly recovered, the slipping of an axe in his hands so
wounded his foot that he was laid up for fully two months more.

It looked as if ill-fortune was to follow him so long at least as he stayed


in South Dakota, for sickness, accident, and misfortune succeeded each
other, until he would have despaired but for those around him.

His wife was well fitted to be the helpmate of a pioneer, for she was
hopeful, industrious, strong, and brave. She carefully nursed him, making
light of their afflictions, and declaring that all would soon come right, and
that prosperity would prove the sweeter from having been deferred so long.

Edith, bright-eyed, pretty, affectionate and loving, was the comfort of


those hours which otherwise would have been intolerably dismal, when
confined in his small humble home. He read to and taught her, told her
delightful fairy stories, listened to her innocent prattle and exchanged the
sweetest of confidences.

Sometimes Hugh Kingsland wondered after all whether he was not the
most fortunate individual in the world in being thus blessed in his family
relations.

And there was another from whom the meed of praise must not be
withheld. That was Brinton, now close upon seventeen years of age. The ill-
fortune to which we have alluded made him in one sense the virtual head of
the family. He was strong, cheerful, and resembled his mother in his
hopeful disposition. The difficulties in which his father was continually
involved brought out the real manhood of his nature. He looked after the
cattle and live stock, galloped across the plains to Hermosa, Fairburn, Rapid
City, and other points for supplies or on other business, or, fording the Big
Cheyenne, White, and smaller streams, crossed the reservation to Pine
Ridge.

The youth was indispensable, and did his work so well, that the father, in
his occasional moments of rallying, remarked that he thought of continuing
to play the sick man, since it was proved that he was of no account.
"I hope you will soon become well," said the red-cheeked lad one
evening, as the group gathered around the fire; "but stay here in the house
as long as you wish, for mother and Edith and I can get along without your
help."

"Yes, husband; don't fret over that. Only become well, and until you do
so, be assured that everything is going along as it should."

"I have never had a doubt of that; but, ah me," he added with a sigh, "this
is tiresome after all, especially when it begins to look as though I shall
never be well again."

"For my part," said Edith very earnestly, "I don't want you to get well,
and I am praying that you will not."

"Why, Edith!" exclaimed the mother reproachfully, while her brother did
not know whether to laugh or be shocked at the odd expression. As for the
father, he laughed more heartily than he had done for weeks.

Edith looked wonderingly in their faces, and felt that some explanation
was due to them.

"I mean to say—that is I don't mean anything bad, but if papa gets well
enough to ride out to look after the cattle, and is working all day, why, I
won't have anyone to tell me stories and read to me and do so many funny
things."

"Your explanation is satisfactory," said her father, smiling. "I shall have
to stay in the house for some weeks—that is certain, and perhaps longer."

"Oh, I am so glad!"

But with the first clapping of the chubby hands, Edith realised that she
was doing wrong again, and she added in a gentler voice—

"If papa feels bad when he is ill then I am sorry for him, and will pray
every night and morning that he may get well."
It was winter time, and the Kingslands in their humble home could not
be ignorant of the alarming state of affairs around them. They had been
urged to come into the agency while it was safe to do so, for the revolt
among the Indians was spreading, and there was no saying when escape
would be cut off. The family had considered the question with the
seriousness due to so important a matter.

Naturally, they were reluctant to abandon their home now, for it would
be virtually throwing away everything they owned in the world; but when it
became a question of life and death, there could be no hesitation.

On the very night, however, that the decision to remove to the agency
was made, Sergeant Victor Parkhurst, who was out on a scout, with a squad
of men from Pine Ridge, called at their home and stated his belief that no
trouble would occur. He said it would be better if the family were at Pine
Ridge, and he offered to escort them thither. But, he added, that in Mr.
Kingsland's feeble condition it would be as well for him to stay where he
was, since he must run great risk by exposure in the depth of winter.

The next caller at the cabin was Nicholas Jackson, who had been a scout
under General Crook, and was now serving General Miles in the same
capacity at Pine Ridge. He brought news of Sitting Bull's death, and assured
the pioneer that every day spent by him and his family away from the
agency increased their peril.

"You shouldn't delay your start a single hour," was his remark, as he
vaulted upon his pony and skurried away.

Before deciding the all-important question, it was agreed that Brinton


should gallop down to the reservation and learn the real situation. It was a
long ride to Pine Ridge, and involved the crossing of the Cheyenne, White,
and several smaller streams, but the youth was confident he could penetrate
far enough to ascertain the truth and get back by sunset. If it were necessary
to go all the way to the agency, this was impossible, for the days were at
their shortest, but he must penetrate that far to find out what he wished to
know.
When Brinton flung himself into the saddle of Jack, his tough and
intelligent pony, just as it was beginning to grow light in the east, after his
hasty breakfast and "good-bye," he was sure he would be caught in a snow-
storm before his return. The dull heavy sky, and the peculiar penetrating
chilliness, left no doubt on that point.

But with his usual pluck, he chirruped to his pony, lightly jerked his
bridle rein, and the gallant animal was off at a swinging pace, which he was
able to maintain for hours without fatigue. He was heading south-east, over
the faintly marked trail, with which the youth was familiar and which was
so well known to the animal himself that he needed no guidance.

Two hours later, the young horseman reached the border line of Custer
and Washington counties, that is between the county of his own home and
the reservation. This was made by the Big Cheyenne River, which had to be
crossed before Pine Ridge was reached. Brinton reined up his horse and sat
for some minutes, looking down on the stream, in which huge pieces of ice
were floating, though it was not frozen over.

"That isn't very inviting, Jack," he said, "but the ford is shallow and it's
no use waiting."

He was in the act of starting his pony down the bank, when on the heavy
chilly air sounded a dull explosive crack. A nipping of his coat sleeve
showed that the bullet had passed startlingly near him. He turned his head
like a flash, and saw, not more than a hundred feet distant, the figure of a
Sioux buck or young warrior bareback on his horse, which was standing
motionless, while his rider made ready to let fly with another shot from his
Winchester rifle.

CHAPTER II.

"HE'S UP TO SOME MISCHIEF, I'LL WARRANT."


The instant Brinton Kingsland looked around and saw the Indian on his
pony, a short distance away, with his rifle at his shoulder and about to fire a
second time, he brought his own Winchester to a level and aimed at the one
who had attempted thus treacherously to shoot him in the back.

The Indian was no older than himself, sitting firmly on the bare back of
his horse, with his blanket wrapped about his shoulders, and several stained
eagle feathers protruding from his hair, as black and coarse as that of his
pony's tail. His dark eyes glittered as they glanced along the barrel of his
rifle, and he aimed straight at the breast of the youth, who instead of
flinging himself over the side of his horse in the attempt to dodge the
deadly missile, sat bolt upright and aimed in turn at the miscreant, who, as
if stirred by the same scorn of personal danger, remained firmly in his seat.

It all depended on who should fire first, and that which we have related
took place, as may be said, in the twinkling of an eye.

But with the weapons poised, the eyes of the two glancing along the
barrels and the fingers on the triggers, neither gun was discharged. Brinton
was on the point of firing, when the Indian abruptly lowered his Winchester,
with the exclamation—

"Hoof! Brinton!"

The white youth had recognised the other at the same instant when
another moment would have been too late. He, too, dropped the stock of his
gun from his shoulder and called out with a surprised expression—

"Wolf Ear!"

The Indian touched his pony with his heel, and the animal moved
forward briskly, until the riders faced each other within arm's length.

"How do you do?" asked the Ogalalla, extending his hand, which
Brinton took with a smile, and the reproving remark—

"I did not expect such a welcome from you, Wolf Ear."
"I did not know it was you, good friend Brinton."

"And suppose you did not; are you the sort of warrior that shoots another
in the back?"

The broad face, with its high cheek bones, coppery skin, low forehead
and Roman nose, changed from the pleasant smile which gave a glimpse of
the even white teeth, to a scowl, that told the ugly feelings that had been
stirred by the questioning remark of the white youth.

"Your people have become my enemies: they have killed Sitting Bull,
Black Bird, Catch-the-Bear, Little Assiniboine, Spotted Horse Bull, Brave
Thunder, and my friend, Crow Foot, who was the favourite son of Sitting
Bull. He was as a brother to me."

"And your people have killed Bull Head, Shave Head, Little Eagle,
Afraid-of-Soldiers, Hawk Man, and others of their own race, who were
wise enough to remain friends of our people. I know of that fight when they
set out to arrest Sitting Bull."

"They had no right to arrest him," said Wolf Ear, with a flash of his black
eyes; "he was in his own tepee (or tent), and harming no one."

"He was doing more harm to his own people as well as ours, than all the
other malcontents together. He was the plotter of mischief; he encouraged
this nonsense about the ghost dances and the coming Messiah, and was
doing all he could to bring about a great war between my people and yours.
His death is the best fortune that could come to the Indians."

"It was murder," said Wolf Ear sullenly, and then, before the other could
frame a reply, his swarthy face lightened up.

"But you and I, Brinton, are friends; I shot at you because I thought you
were someone else; it would have grieved my heart had I done you harm; I
am glad I did not; I offer you my hand."

Young Kingsland could not refuse the proffer, though he was far from
feeling comfortable, despite his narrow escape a moment before.
"I thought you were a civilised Indian, Wolf Ear," he added, as he
relinquished the grasp, and the two once more looked in each other's
countenances; "you told me so when I last saw you."

Wolf Ear, the Ogalalla, was sent to Carlisle, when only eight years old.
Unusually bright, he had made good progress, and won the golden opinions
of his teachers by his gentle, studious deportment, and affection for those
that had been kind to him.

He spoke English as well as the whites, and was a fine scholar. He went
back to his people, when sixteen years old, and did what he could to win
them from their savagery and barbarism.

He and Brinton Kingsland met while hunting at the base of the Black
Hills, and became great friends. The young Ogalalla visited the white youth
at his home on Raccoon Creek, where he was kindly treated by the
Kingslands, and formed a deep affection for little Edith.

But nothing had been seen of Wolf Ear for several months. The home of
his people was some distance away, but that should not have prevented him
from visiting his white friends, who often wondered why he did not show
himself among them.

Rather curiously, Brinton was thinking of his dusky comrade at the


moment he was roused by the shot which nipped his coat sleeve. It was
natural that he should be disappointed, and impatient to find that this bright
Indian youth, who had lived for several years among civilised people, was
carried away by the wave of excitement that was sweeping across the
country. He knew that his twin brother and his father were still savages, and
it was easy to find excuse for them, but not for Wolf Ear.

"You believe in the coming of One to save your people—why should not
we place faith in the coming of our Messiah?" was the pertinent question of
Wolf Ear.

"What is this revelation?" asked Brinton, who had heard many


conflicting accounts of the strange craze, and felt a natural desire for an
authoritative statement.
"The Messiah once descended to save the white race, but they rejected
and put him to death. In turn he rejects them, and will come in the spring,
when the grass is about two inches high, and save his red children and
destroy his white ones. He has enjoined upon all of us who believe in him
to wear a certain dress and to practise the ghost dance, as often and as long
as we possibly can, as a proof of our faith. If any of us die from exhaustion,
while performing this ceremony, we will be taken direct to the Messiah,
where we shall meet those who have died, and whence we will come back
to tell the living what we have seen and heard. When the Messiah comes in
the spring, a new earth will be created, covering the present world, burying
all the whites and those red men that have not joined in the dance. The
Messiah will again bring with him the departed of our own people, and the
earth shall once more be as our forefathers knew it, except there shall be no
more death."

Brinton Kingsland listened, amazed as this expression fell from the lips
of one who had often lamented the superstition of his own race. That he
believed the words he uttered was proven by his earnestness of manner and
the glow of his countenance. The white youth restrained his impulse to
ridicule the strange faith, for that assuredly would have given offence to the
fanatic, who had the right to believe whatever he chose.

"Well, Wolf Ear, I can only say I am sorry that you should have been
carried away by this error——"

"By what right do you call it error?" interrupted the other with a flash of
his eyes.

"We will not discuss it. It will do no good, and is likely to do harm. I
need not be told that you belong to the hostiles, and, if trouble comes, will
fight against the whites."

"Yes, you are right," calmly replied the Ogalalla, compressing his thin
lips and nodding his head a single time.

"Your father and brother, whom I have never seen, would shoot me and
my folk if they had the chance."
"Yes, and so would my mother: she is a warrior too."

"But suppose you and I or my father meet, or you have the chance to
harm my mother and little sister, Edith?"

"Wolf Ear can never raise his hand against them, no matter what harm
they may seek to do him. I do not have to tell you that you and I will always
be friends, whatever may come."

This assurance would have had more weight with young Kingsland
could he have felt certain that Wolf Ear was truthful in declaring that he did
not suspect his identity at the moment of firing at him.

"I believe he meant to take my life," was his thought, "and still meant to
do so, when he raised his Winchester a second time, but as we looked into
each other's face, he weakened. His people are treacherous, and this
pretence of goodwill will not last, or, if it be genuine for the present, it will
soon change."

Brinton said—

"You know where we live, Wolf Ear; I have set out to ride to the
reservation to learn whether it is safe to stay where we are: what is your
judgment in the matter?"

An indefinable expression passed over the broad face before him. The
Ogalalla sat gracefully on his horse, even though he had no saddle. A bit
was in the pony's mouth, the single rein looping around the neck and resting
at the base of the mane, just in front of the rider, who allowed it to lie there,
while the two hands idly held the rifle across the back of the animal and his
own thighs.

"You stayed too long," said he; "you should have left two weeks ago; it
is too late now."

"But you know my father is not well, Wolf Ear," replied Brinton, with a
sickening dread in his heart.
"What has that to do with this?"

"We did not wish to expose him to the severe weather, as we must in the
ride to the agency."

"Is he better and stronger now?"

"There is little improvement in his condition. He has been ailing a long


time, as you know."

"Then you have gained nothing and will lose all by your delay."

Brinton had no further wish to discuss the ghost dance and the coming of
the new Messiah with the young Ogalalla. All his thoughts were of those
dear ones, miles away, whose dreadful peril he now fully comprehended for
the first time. He saw the mistake that had been made by the delay, and a
faintness came over him at the declaration of Wolf Ear that this delay was
fatal.

His horse was facing the north-west, the direction of his home. There
was no call for longer tarrying.

"Good-bye," he said, giving the Indian a military salute; "I hope we shall
meet ha more pleasant circumstances, when you shall see, Wolf Ear, the
mistake you are making."

Trained in the ways of the white people, the dusky youth raised his hand
to his forehead, and sat motionless on his horse, without speaking, as his
friend dashed across the plain, over the trail which he had followed to the
banks of the Big Cheyenne.

It was not yet noon, and Brinton was hopeful of reaching home long
before the day drew to a close. The chilliness of the air continued, and a few
feathery flakes of snow drifted horizontally on the wind or were whirled
about the head of the young horseman. He glanced up at the leaden sky and
noted that the temperature was falling.
"Like enough we shall have one of those blizzards, when the horses and
cattle freeze to death under shelter and we can only huddle and shiver
around the fire and wait for the tempest to pass. It will be the death of us all,
if we start for the agency and are caught in one of the blizzards, but death
awaits us if we stay. Ah me, what will become of father, ill and weak as he
is?"

The words of Wolf Ear made the youth more circumspect and alert than
when riding away from his home. He continually glanced ahead, on his
right and left and to the rear. The first look in the last direction showed him
the young Ogalalla sitting like a statue on his pony and gazing after him.

Some minutes later, when Brinton turned his head again, he saw him
riding at a rapid pace towards the north, or rather a little west of north, so
that the course of the two slightly diverged.

"He's up to some mischief, I'll warrant," was Brinton's conclusion, "and


he already recalls his profession of friendship for me. Halloa! I don't like
the look of that."

In the precise direction pursued by the Ogalalla, which was toward


Rapid Creek, a tributary of the Big Cheyenne, he discerned several Indian
horsemen. They were riding close, and were so mingled together that it was
impossible to tell their number. They seemed to be about half a dozen, and
were advancing as if to meet Wolf Ear, who must have descried them before
Brinton.

"They will soon unite, and when they do he will be the fiercest warrior
among them. I wonder——"

He held his breath a moment, and then only whisper—

"I wonder if they have not already visited our home?"


CHAPTER III.

"THERE ARE FIFTY HOSTILES."

To the westward the Black Hills thrust their vast rugged summits against
the wintry sky; to the south, a spur of the same mountains put out toward
the frontier town of Buffalo Gap; to the north-east wound the Big
Cheyenne, on its way to the Missouri, and marking through a part of its
course the southern boundary of the Cheyenne Reservation, while creek,
stream, and river crossed the rolling plain that intervened, and over all
stretched the sunless sky, from which the snow-flakes were eddying and
whirling to the frozen earth below.

But Brinton Kingsland had no eye for any of these things, upon which he
had looked many a time and oft. His thoughts were with those loved ones in
the humble cabin, still miles away, toward the towering mountains, while
his immediate anxiety was about the hostiles that had appeared in his front
and were now circling to the northward as if to meet Wolf Ear, the young
Ogalalla, who was galloping in the face of the biting gale and rapidly
drawing toward them.

Brinton's expectation that they would lose no time in coming together


was not precisely fulfilled, for while the horsemen were yet a long way off,
they swerved sharply, as though they identified the youth for the first time.

"They intend to give me some attention," was his thought, "without


waiting for Wolf Ear to join them. They know that I belong to the white
race, and that is enough."

The youth did not feel any special alarm for himself, for he was
confident that Jack was as fleet-footed as any of the animals bestrode by the
hostiles, and would leave them behind in a fair race. He noticed that the
Ogalalla was mounted on a superior beast, but he did not believe he could
outspeed Jack.

But it would never do to meet those half-dozen horsemen that had faced
toward him, and were approaching at the same swinging gallop. Brinton
diverged more to the left, thus leaving the trail, and they also changed their
course, as if to head him off.

"If it is to be a race, I am throwing away my chances by helping to


shorten the distance between us."

The fugitive now headed directly away from the horsemen, so that both
parties were pursuing the same line. The youth looked back, at the moment
that several blue puffs of smoke showed over the backs of the horses. The
thudding reports came through the chilly air, and a peculiar whistling sound
overhead left no doubt that the hostiles, great as was the separating space,
had fired at the fugitive, who turned to take a look at Wolf Ear.

That individual discharged his gun the next moment. Brinton heard
nothing of the bullet, but smiled grimly—

"He has changed his mind soon, but they have got to come closer before
they hurt me. He is no great marksman anyway, or he would not have
missed me a little while ago."

It was singular that it did not occur to young Kingsland that it was
possible the Ogalalla had not fired at him at all. Not even when the
horsemen checked their pursuit, and reining up their animals awaited the
coming of the buck, who was riding like a hurricane, could he bring himself
to think of Wolf Ear except as a bitter enemy, who for some subtle purpose
of his own had declared a temporary truce.

"I suppose they think I shall be along this way again pretty soon, and
they can afford to wait till I run into their trap," was the conclusion of
Brinton, who headed his pony once more toward his home, and put him to
his best paces.

"Come, Jack, there's no time to throw away; hard work is before you,
and you must struggle as never before."

The snowfall which seemed for ever impending did not come. The few
scattering flakes still circled and eddied through the air, as if reluctant to
touch the earth, but no perceptible increase appeared in their number. The
nipping air seemed to have become too cold to permit a snow-storm.

Brinton had set out fully prepared for such change of temperature. He
wore a thick woollen cap, whose flaps were drawn down to his ears, while
they were more than met by the heavy coat collar that was turned up, the
garment itself being closely buttoned around his body. His rifle rested
across the pommel of his saddle in front, and his gloved hands scarcely ever
touched the rein which lay loose on his pony's neck. He was a capital
horseman, and, with the understanding between him and his intelligent
beast, could have got along without any bit at all.

Strapped behind him was a substantial lunch, and his keen appetite
would have made it enjoyable, but he did not disturb it. It could wait until
he learned the truth about the folk at home, which he was now rapidly
drawing near.

Over a swell in the prairie, across a small creek, whose icy waters hardly
came above Jack's fetlocks, up a second rise, and then Brinton Kingsland
uttered an exclamation of amazement and sharply checked his animal.

"My gracious! what is the meaning of that?"

Over another swell, and only a few hundred yards away, two other
horses rode to view, coming directly toward him. Each sustained a heavily
muffled figure, and they were moving at a rapid walk.

Suspecting their identity, he waited a minute, and then started his horse
forward again. A few paces, and despite the arctic temperature, he raised his
cap from his head and called out—

"Hurrah! thank Heaven, you are alive, and have started for the agency."

His father sat on one horse, swathed in heavy clothing, and a blanket
which the faithful wife had fastened around his emaciated and weak form,
while she, with Edith in front, and both also protected against the severe
weather, were on the other animal. He had a rifle across his saddle front,
like the son, and they had brought with them nothing but a small amount of
food, barely enough to last them until they could reach the agency, provided
there was no unexpected delay on the road.

The discovery that they were alive and secure for the time, though the
shadow of a great peril was over all, so delighted the son that he could not
repress the shout of joy, as he rode forward and greeted them, little more
than their eyes and noses showing through the thick coverings.

"What made you leave before I got back?" was the first inquiry of
Brinton, after a few congratulatory words.

"We concluded it was high time to do so," replied the father, showing
more vigour in his voice than the son expected.

"How did you find it out?"

"A half-dozen hostiles fired several times at the house, and then, as if
they feared they were not strong enough to capture us and burn the cabin,
rode off for help."

"They are hardly out of sight now; they gave me half a dozen shots, and
I had a short chase with them. But you are off the trail."

"And so are you," said his father.

"Which is a mighty good thing for us both. You had to abandon


everything?"

"Of course; I have no doubt though," added the father grimly, "that the
Indians will look after the live stock for us."

"Whom do you suppose I saw?" asked Brinton, turning to his mother and
sister.

"A big bear?" ventured Edith from the depths of her wrappings.

"No; he was an old friend of yours—Wolf Ear, who used to come to our
house and have such good times with you."
The excited child flung her arms about in the effort to free herself of the
encumbering wrappings.

"Oh, where is he? Why didn't he come with you? Didn't he want to see
me? I am so sorry; isn't he with you?"

And she peered around, as if she suspected the young Ogalalla was
hiding behind the saddle of her brother.

Brinton smiled, and then gravely shook his head. He said, addressing his
parents more than the little one—

"I was never more astonished than to find that Wolf Ear, despite the
training he has had at Carlisle, has joined the hostiles, and is now an enemy
of those who were such good friends of his."

The youth did not think it wise to tell, in the presence of his sister, the
particulars of their first meeting.

"You grieve me more than I can express," replied the father; "are you
sure you are not mistaken?"

"Not when he told me so himself."

"But you must have met as friends."

"He said he would not harm any one of us, if the fortunes of war should
give him the chance; but he declares himself the enemy of all others of our
race. He has a twin brother, and he and his father and mother, as Wolf Ear
coolly told me, would be pleased to scalp us. I have no more faith in him
than in them. We parted as friends, but he has joined that very party which
fired on you, and will go back to the house with them."

"And finding us gone, what then?"

"He will lead them on our trail and be among the foremost to shoot us
down, every one of us."
"I don't believe it!" called Edith from her wraps, which her mother had
put around her again; "I like Wolf Ear and want to see him."

Brinton did not think it worth while to discuss the matter with his sister,
for a far more important matter pressed upon them.

"It won't do to follow the trail," remarked the father, "since they will be
on the look-out for us. We will bear to the south, so as to strike the
Cheyenne further up stream."

"We may not be able to ford it."

"We can follow it down till we find a place. It may be frozen over nearer
its source. The agency is so far off that we shall have to go into camp before
we can get half-way there."

"How do you feel, father?" abruptly asked his son, glancing keenly at
him. "Are you strong enough to stand this hard ride?"

"I am much stronger than you would suppose; you know a crisis like this
will rouse any man, even if he is a good deal more unwell than I am."

"I am glad to hear you talk that way, but you will be tried hard before we
reach Pine Ridge."

"Give yourself no uneasiness about me; the only thing we are to think
about is how we shall get to the agency without meeting with the hostiles,
who seem to be roaming everywhere."

While they sat talking, at the base of the swell, on the summit of which
the parents had first appeared, all partook of lunch, for it was not likely they
would have a more favourable opportunity before the coming of night.

It was decided to bear still more to the south, with a view of avoiding the
party that was at no great distance. Indeed, less than half an hour had passed
since they vanished from the view of the youth, who believed they were
waiting in the vicinity of the trail for his return, and would attack the whites
the moment they discovered them.
The halt lasted little more than a quarter of an hour, when they resumed
their journey toward the agency, which they hoped, rather than expected, to
reach by the morrow's set of sun. The mother was without any weapon,
though she was quite skilful in the use of a rifle. Her husband said that if he
found himself compelled to yield to weakness, he would turn over his
Winchester to her, believing as he did that she was sure to give a good
account of herself.

They were plentifully supplied with cartridges, but the reader does not
need to be reminded of their almost helpless situation. Kingsland, despite
his brave efforts to keep up, was unable to ride his pony at full speed for
any length of time, while the wife, burdened with the care of Edith, could
not expect to do much better.

If the company were attacked by any party of hostiles, however slight in


numbers, deplorable consequences were almost certain. Their hope would
be in finding some sort of shelter which might be turned to account as a
screen or barricade.

But their only safety, it may be said, lay in avoiding the Indians
altogether, and it was to that task that Brinton, as the strongest one of the
party, addressed himself with all the energy and skill of his nature.

The course was up and down continually, though none of the swells in
the prairie was of much height. The youth rode slightly in advance and
never made his way to the top of one of the slight elevations without a
quicker throbbing of the heart and a misgiving which made the situation of
the most trying nature.

It was the dread of the hostiles, with whom Wolf Ear had joined himself,
that led him to make a longer bend to the south than even his father had
contemplated. True, as he well knew, they were not the sole Indians to be
dreaded, but they were the only ones of whom he had positive knowledge.
Others were likely to be encountered at any time, and it may be said that as
they drew nearer the agency, the peril increased.

A half-dozen miles from where the family had been reunited, they
approached a higher elevation than any that had yet been crossed. Brinton
asked the rest to halt at the base, while he dismounted and carefully went to
the top on foot.

It was well he took this precaution, for his friends, who were watching
his crouching figure as he cautiously went up the incline, saw him abruptly
halt and peer over the ridge, in a way which showed he had perceived
something. He remained but a minute, when he hurried back, pale and
excited.

"There are fifty hostiles!" he exclaimed in an undertone, "and they are


only a little way off!"

CHAPTER IV.

"WE ABE ENEMIES."

Brinton Kingsland, after peering over the crest of the elevation for a few
brief moments, turned and hastily descended to where his pony awaited
him. Without touching his bridle, he spoke, and the obedient animal
followed him, while the parents and little sister anxiously listened to the
report of what he learned.

"It's the very party of Indians that we have been trying to get away
from," added the youth to his first explanation; "there are seven of them,
and Wolf Ear is among them."

"Is he?" eagerly asked Edith, from her wrappings on the saddle in front
of her mother "oh, let me see him! Tell him I am here."

"Keep quiet! Don't speak," said her father sternly. "Wolf Ear is with bad
Indians, and is a bad Indian himself"

You might also like