Emulation of the 1970's Chip-8 machine. The emulator has 7 games that are unmodified from the original Chip-8 format.
main.cpp@0:bc3f11b1b41f, 2015-02-08 (annotated)
- Committer:
- taylorza
- Date:
- Sun Feb 08 01:58:57 2015 +0000
- Revision:
- 0:bc3f11b1b41f
Chip-8 Emulator
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
taylorza | 0:bc3f11b1b41f | 1 | #include "mbed.h" |
taylorza | 0:bc3f11b1b41f | 2 | #include "LCD_ST7735.h" |
taylorza | 0:bc3f11b1b41f | 3 | #include "Color565.h" |
taylorza | 0:bc3f11b1b41f | 4 | #include "font_OEM.h" |
taylorza | 0:bc3f11b1b41f | 5 | #include "GameInput.h" |
taylorza | 0:bc3f11b1b41f | 6 | #include "Chip8Emulator.h" |
taylorza | 0:bc3f11b1b41f | 7 | |
taylorza | 0:bc3f11b1b41f | 8 | #include "SpaceInvadersGame.h" |
taylorza | 0:bc3f11b1b41f | 9 | #include "BrixGame.h" |
taylorza | 0:bc3f11b1b41f | 10 | #include "BlinkyGame.h" |
taylorza | 0:bc3f11b1b41f | 11 | #include "PongGame.h" |
taylorza | 0:bc3f11b1b41f | 12 | #include "TetrisGame.h" |
taylorza | 0:bc3f11b1b41f | 13 | #include "MissileGame.h" |
taylorza | 0:bc3f11b1b41f | 14 | #include "UfoGame.h" |
taylorza | 0:bc3f11b1b41f | 15 | |
taylorza | 0:bc3f11b1b41f | 16 | LCD_ST7735 screen(P0_19, P0_20, P0_7, P0_21, P0_22, P1_15, P0_2, LCD_ST7735::RGB); |
taylorza | 0:bc3f11b1b41f | 17 | |
taylorza | 0:bc3f11b1b41f | 18 | |
taylorza | 0:bc3f11b1b41f | 19 | void menu(const uint8_t **program, uint16_t &programSize, uint8_t &leftKey, uint8_t &rightKey, uint8_t &upKey, uint8_t &downKey, uint8_t &fireKey, uint8_t &startKey); |
taylorza | 0:bc3f11b1b41f | 20 | void drawString(const uint8_t *pFont, int y, const char *string); |
taylorza | 0:bc3f11b1b41f | 21 | |
taylorza | 0:bc3f11b1b41f | 22 | main() |
taylorza | 0:bc3f11b1b41f | 23 | { |
taylorza | 0:bc3f11b1b41f | 24 | screen.setOrientation(LCD_ST7735::Rotate270, false); |
taylorza | 0:bc3f11b1b41f | 25 | |
taylorza | 0:bc3f11b1b41f | 26 | const uint8_t *program; |
taylorza | 0:bc3f11b1b41f | 27 | uint16_t programSize; |
taylorza | 0:bc3f11b1b41f | 28 | uint8_t leftKey; |
taylorza | 0:bc3f11b1b41f | 29 | uint8_t rightKey; |
taylorza | 0:bc3f11b1b41f | 30 | uint8_t upKey; |
taylorza | 0:bc3f11b1b41f | 31 | uint8_t downKey; |
taylorza | 0:bc3f11b1b41f | 32 | uint8_t fireKey; |
taylorza | 0:bc3f11b1b41f | 33 | uint8_t startKey; |
taylorza | 0:bc3f11b1b41f | 34 | |
taylorza | 0:bc3f11b1b41f | 35 | menu(&program, programSize, leftKey, rightKey, upKey, downKey, fireKey, startKey); |
taylorza | 0:bc3f11b1b41f | 36 | Chip8Emulator emulator(screen, program, programSize, leftKey, rightKey, upKey, downKey, fireKey, startKey); |
taylorza | 0:bc3f11b1b41f | 37 | emulator.run(); |
taylorza | 0:bc3f11b1b41f | 38 | } |
taylorza | 0:bc3f11b1b41f | 39 | |
taylorza | 0:bc3f11b1b41f | 40 | struct MenuItem |
taylorza | 0:bc3f11b1b41f | 41 | { |
taylorza | 0:bc3f11b1b41f | 42 | const char *Text; |
taylorza | 0:bc3f11b1b41f | 43 | const uint8_t *Program; |
taylorza | 0:bc3f11b1b41f | 44 | const uint16_t ProgramSize; |
taylorza | 0:bc3f11b1b41f | 45 | const uint8_t LeftKey; |
taylorza | 0:bc3f11b1b41f | 46 | const uint8_t RightKey; |
taylorza | 0:bc3f11b1b41f | 47 | const uint8_t UpKey; |
taylorza | 0:bc3f11b1b41f | 48 | const uint8_t DownKey; |
taylorza | 0:bc3f11b1b41f | 49 | const uint8_t FireKey; |
taylorza | 0:bc3f11b1b41f | 50 | const uint8_t StartKey; |
taylorza | 0:bc3f11b1b41f | 51 | |
taylorza | 0:bc3f11b1b41f | 52 | MenuItem(const char *text, const uint8_t *program, const uint16_t programSize, uint8_t leftKey, uint8_t rightKey, uint8_t upKey, uint8_t downKey, uint8_t fireKey, uint8_t startKey) : |
taylorza | 0:bc3f11b1b41f | 53 | Text(text), |
taylorza | 0:bc3f11b1b41f | 54 | Program(program), |
taylorza | 0:bc3f11b1b41f | 55 | ProgramSize(programSize), |
taylorza | 0:bc3f11b1b41f | 56 | LeftKey(leftKey), |
taylorza | 0:bc3f11b1b41f | 57 | RightKey(rightKey), |
taylorza | 0:bc3f11b1b41f | 58 | UpKey(upKey), |
taylorza | 0:bc3f11b1b41f | 59 | DownKey(downKey), |
taylorza | 0:bc3f11b1b41f | 60 | FireKey(fireKey), |
taylorza | 0:bc3f11b1b41f | 61 | StartKey(startKey) |
taylorza | 0:bc3f11b1b41f | 62 | { |
taylorza | 0:bc3f11b1b41f | 63 | |
taylorza | 0:bc3f11b1b41f | 64 | } |
taylorza | 0:bc3f11b1b41f | 65 | }; |
taylorza | 0:bc3f11b1b41f | 66 | |
taylorza | 0:bc3f11b1b41f | 67 | MenuItem menuItems[] = |
taylorza | 0:bc3f11b1b41f | 68 | { |
taylorza | 0:bc3f11b1b41f | 69 | MenuItem("Invaders", SpaceInvadersGame, sizeof(SpaceInvadersGame), 4, 6, 2, 8, 5, 15), |
taylorza | 0:bc3f11b1b41f | 70 | MenuItem("Brix", BrixGame, sizeof(BrixGame), 4, 6, 2, 8, 5, 15), |
taylorza | 0:bc3f11b1b41f | 71 | MenuItem("Blinky", BlinkyGame, sizeof(BlinkyGame), 7, 8, 3, 6, 1, 15), |
taylorza | 0:bc3f11b1b41f | 72 | MenuItem("Tetris", TetrisGame, sizeof(TetrisGame), 5, 6, 4, 0, 0, 0), |
taylorza | 0:bc3f11b1b41f | 73 | MenuItem("Pong", PongGame, sizeof(PongGame), 0, 0, 1, 4, 0, 0), |
taylorza | 0:bc3f11b1b41f | 74 | MenuItem("Missile", MissileGame, sizeof(MissileGame), 8, 8, 8, 8, 8, 8), |
taylorza | 0:bc3f11b1b41f | 75 | MenuItem("UFO", UfoGame, sizeof(UfoGame), 4, 6, 5, 8, 5, 15), |
taylorza | 0:bc3f11b1b41f | 76 | }; |
taylorza | 0:bc3f11b1b41f | 77 | |
taylorza | 0:bc3f11b1b41f | 78 | void drawString(const uint8_t *pFont, int y, const char *string) |
taylorza | 0:bc3f11b1b41f | 79 | { |
taylorza | 0:bc3f11b1b41f | 80 | uint8_t w; |
taylorza | 0:bc3f11b1b41f | 81 | uint8_t h; |
taylorza | 0:bc3f11b1b41f | 82 | screen.measureString(pFont, string, w, h); |
taylorza | 0:bc3f11b1b41f | 83 | screen.drawString(pFont, (screen.getWidth() - w) / 2, y, string); |
taylorza | 0:bc3f11b1b41f | 84 | } |
taylorza | 0:bc3f11b1b41f | 85 | |
taylorza | 0:bc3f11b1b41f | 86 | void menu(const uint8_t **program, uint16_t &programSize, uint8_t &leftKey, uint8_t &rightKey, uint8_t &upKey, uint8_t &downKey, uint8_t &fireKey, uint8_t &startKey) |
taylorza | 0:bc3f11b1b41f | 87 | { |
taylorza | 0:bc3f11b1b41f | 88 | screen.clearScreen(); |
taylorza | 0:bc3f11b1b41f | 89 | |
taylorza | 0:bc3f11b1b41f | 90 | drawString(font_oem, 0, "CHIP-8 Emulator"); |
taylorza | 0:bc3f11b1b41f | 91 | drawString(font_oem, 120, "(c)2015 Chris Taylor"); |
taylorza | 0:bc3f11b1b41f | 92 | |
taylorza | 0:bc3f11b1b41f | 93 | int itemCount = sizeof(menuItems) / sizeof(menuItems[0]); |
taylorza | 0:bc3f11b1b41f | 94 | int selectedItem = 0; |
taylorza | 0:bc3f11b1b41f | 95 | int counter = 0; |
taylorza | 0:bc3f11b1b41f | 96 | while(true) |
taylorza | 0:bc3f11b1b41f | 97 | { |
taylorza | 0:bc3f11b1b41f | 98 | counter++; |
taylorza | 0:bc3f11b1b41f | 99 | for (int i = 0; i < itemCount; ++i) |
taylorza | 0:bc3f11b1b41f | 100 | { |
taylorza | 0:bc3f11b1b41f | 101 | if (selectedItem == i) |
taylorza | 0:bc3f11b1b41f | 102 | { |
taylorza | 0:bc3f11b1b41f | 103 | screen.setForegroundColor(Color565::Yellow); |
taylorza | 0:bc3f11b1b41f | 104 | screen.setBackgroundColor(Color565::Blue); |
taylorza | 0:bc3f11b1b41f | 105 | } |
taylorza | 0:bc3f11b1b41f | 106 | else |
taylorza | 0:bc3f11b1b41f | 107 | { |
taylorza | 0:bc3f11b1b41f | 108 | screen.setForegroundColor(Color565::Yellow); |
taylorza | 0:bc3f11b1b41f | 109 | screen.setBackgroundColor(Color565::Black); |
taylorza | 0:bc3f11b1b41f | 110 | } |
taylorza | 0:bc3f11b1b41f | 111 | |
taylorza | 0:bc3f11b1b41f | 112 | int menuTop = (screen.getHeight() - (itemCount * 10)) / 2; |
taylorza | 0:bc3f11b1b41f | 113 | drawString(font_oem, menuTop + (i * 10), menuItems[i].Text); |
taylorza | 0:bc3f11b1b41f | 114 | } |
taylorza | 0:bc3f11b1b41f | 115 | |
taylorza | 0:bc3f11b1b41f | 116 | if (GameInput::isUpPressed()) |
taylorza | 0:bc3f11b1b41f | 117 | { |
taylorza | 0:bc3f11b1b41f | 118 | --selectedItem; |
taylorza | 0:bc3f11b1b41f | 119 | if (selectedItem < 0) selectedItem = itemCount - 1; |
taylorza | 0:bc3f11b1b41f | 120 | wait_ms(200); |
taylorza | 0:bc3f11b1b41f | 121 | } |
taylorza | 0:bc3f11b1b41f | 122 | else if (GameInput::isDownPressed()) |
taylorza | 0:bc3f11b1b41f | 123 | { |
taylorza | 0:bc3f11b1b41f | 124 | ++selectedItem; |
taylorza | 0:bc3f11b1b41f | 125 | if (selectedItem >= itemCount) selectedItem = 0; |
taylorza | 0:bc3f11b1b41f | 126 | wait_ms(200); |
taylorza | 0:bc3f11b1b41f | 127 | } |
taylorza | 0:bc3f11b1b41f | 128 | else if (GameInput::isCirclePressed()) |
taylorza | 0:bc3f11b1b41f | 129 | { |
taylorza | 0:bc3f11b1b41f | 130 | *program = menuItems[selectedItem].Program; |
taylorza | 0:bc3f11b1b41f | 131 | programSize = menuItems[selectedItem].ProgramSize; |
taylorza | 0:bc3f11b1b41f | 132 | leftKey = menuItems[selectedItem].LeftKey; |
taylorza | 0:bc3f11b1b41f | 133 | rightKey = menuItems[selectedItem].RightKey; |
taylorza | 0:bc3f11b1b41f | 134 | upKey = menuItems[selectedItem].UpKey; |
taylorza | 0:bc3f11b1b41f | 135 | downKey = menuItems[selectedItem].DownKey; |
taylorza | 0:bc3f11b1b41f | 136 | fireKey = menuItems[selectedItem].FireKey; |
taylorza | 0:bc3f11b1b41f | 137 | startKey = menuItems[selectedItem].StartKey; |
taylorza | 0:bc3f11b1b41f | 138 | |
taylorza | 0:bc3f11b1b41f | 139 | wait_ms(200); |
taylorza | 0:bc3f11b1b41f | 140 | srand(counter); |
taylorza | 0:bc3f11b1b41f | 141 | return; |
taylorza | 0:bc3f11b1b41f | 142 | } |
taylorza | 0:bc3f11b1b41f | 143 | } |
taylorza | 0:bc3f11b1b41f | 144 | } |