From 9880e3b52ca7922d7cb0fa262af262274e1c78ff Mon Sep 17 00:00:00 2001 From: Ghostie Date: Sat, 8 Feb 2025 17:46:53 -0500 Subject: [PATCH] in the beginning, there was darkness --- .clang-format | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 2 + Makefile | 24 +++++ Notes.org | 95 +++++++++++++++++ src/main.c | 38 +++++++ 5 files changed, 433 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 Notes.org create mode 100644 src/main.c diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..2aaef5f --- /dev/null +++ b/.clang-format @@ -0,0 +1,274 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: All +AlwaysBreakBeforeMultilineStrings: false +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterReturnType: AllDefinitions +BreakArrays: true +BreakBeforeBinaryOperators: All +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: GNU +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +BreakTemplateDeclarations: MultiLine +ColumnLimit: 79 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: true + AtStartOfFile: true +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MainIncludeChar: Quote +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: Always +SpaceBeforeParensOptions: + AfterControlStatements: false + AfterForeachMacros: false + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: false + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: c++03 +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TableGenBreakInsideDAGArg: DontBreak +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17fbe89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.out diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dcf7bfb --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +CC=gcc +ECHO=echo -e +CFLAGS=-Wall -Werror -std=gnu99 -O0 -g -Iinclude +LIBS=-lSDL2 + +FILES=build/main.o +OUT=bin/chip8.out + +all: $(FILES) + @$(ECHO) "CC\t\t"$(FILES) + @$(CC) $(CFLAGS) $(FILES) -o $(OUT) $(LIBS) + +build/main.o: src/main.c + @$(ECHO) "CC\t\t"$< + @$(CC) $(CFLAGS) $< -c -o $@ $(LIBS) + +run: all + @$(ECHO) "Runing the Chip8 compiler" + @$(OUT) + +clean: + @$(ECHO) "Cleaning files..." + @rm -f $(FILES) $(OUT) + @$(ECHO) "Cleaning complete..." diff --git a/Notes.org b/Notes.org new file mode 100644 index 0000000..d70fce7 --- /dev/null +++ b/Notes.org @@ -0,0 +1,95 @@ +* Chip8 Emulator + +** The memory Layout + +The Chip8 has 4095 bytes of memory: + +#+begin_src artist + +-----------------------+ + | | 0xFFF - End of Memory + +-----------------------+ + | | + | | + | | + | 0x200/0xFFF | + | ProgramData | + | | + | | + +-----------------------+ 0x200 - Start of Chip8 programs + | | + | 0x00/0x1FF | + | Reserved for Chip8 | + | | + +-----------------------+ 0x00 - Start of Chip8 RAM +#+end_src + +Chip-8 has a stack that is an array of 16 16-bit values, used to store the +addresses that the Chip8 should return to when returning from a subroutine, +meaning there can be 16 levels of nested subroutines. + +** Registers + +Chip8 has 16 8-bit data registers, each can hold 1 byte of information. + +| Data Registers | +|----------------| +| V0 | +| V1 | +| V2 | +| V3 | +| V4 | +| V5 | +| V6 | +| V7 | +| V8 | +| V9 | +| VA | +| VB | +| VC | +| VD | +| VE | +| VF | + +That means that the registers should be implemented as an array with a size of +16: + +| V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | ... | + +The Chip 8 also has some extra registers: +- *I* - used to store memory addresses. +- *PC* - points to the address oft he current instruction being executed. All the + instructions are 2 bytes in size, so this should be incremented by 2 per + instruction executed. +- *SP* - 8-bit stack pointer, points to a location in the stack. +- *Sound Timer*: + - Chip8 plays a beep when the sound timer is not zero + - Decrements at a rate of 70hz + - When zero no sound is played +- *Delay Timer*: + - Chip8 stops executing instructions when the delay timer is greater than + zero. + - This is also decremented at a rate of 60hz. + - When the delay timer is zero, the program execution resumes. + +** The Display + +The size of the display is 64x32 pixels, and it's monocrome. Drawing to the +display is done with sprites, not pixels. If a sprite overflows the screen, it +wraps it back to the other side. The sprites can be a maximum of 8 bits of +width, and up to 15 bytes in length. + +** The Keyboard + +The Chip-8 keyboard has 16 keys: from 0 to F. + +This is how the keyboard looks: + +| 1 | 2 | 3 | C | +| 4 | 5 | 6 | D | +| 7 | 8 | 9 | E | +| A | 0 | B | F | + +** Instruction Set + +The Chip-8 instruction set has 36 different insturctions. These instructions can +be for mathematical operations, drawing and more. diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f598dde --- /dev/null +++ b/src/main.c @@ -0,0 +1,38 @@ +#include +#include + +int +main (int argc, char **argv) +{ + SDL_Init (SDL_INIT_EVERYTHING); + SDL_Window *window + = SDL_CreateWindow ("Chip8", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, 640, 320, SDL_WINDOW_SHOWN); + + SDL_Renderer *renderer + = SDL_CreateRenderer (window, -1, SDL_TEXTUREACCESS_TARGET); + while (1) + { + SDL_Event event; + while (SDL_PollEvent (&event)) + { + if (event.type == SDL_QUIT) + { + goto out; + } + } + + SDL_SetRenderDrawColor (renderer, 0, 0, 0, 0); + SDL_RenderClear (renderer); + + SDL_SetRenderDrawColor (renderer, 255, 255, 255, 0); + SDL_Rect r = { 0, 0, 40, 40 }; + SDL_RenderFillRect (renderer, &r); + + SDL_RenderPresent (renderer); + } + +out: + SDL_DestroyWindow (window); + return 0; +}