From 93368af8f547b8674d13fdbd4582d88b504f9801 Mon Sep 17 00:00:00 2001 From: Stefan Wessels Date: Tue, 10 Sep 2024 01:24:48 -0700 Subject: [PATCH] Spelling, bugs, cleanup --- src/mmm/README.md | 2 +- src/mmm/src/6502.h | 6 +--- src/mmm/src/mmm.c | 77 ++++++++++++++++++++++------------------------ 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/src/mmm/README.md b/src/mmm/README.md index f808e42..2ac06a9 100644 --- a/src/mmm/README.md +++ b/src/mmm/README.md @@ -10,7 +10,7 @@ My speaker code is beyond terrible, but I'll maybe figure that out later. Turn | --- | --- | 6502.c | The 6502 Machine | mminer.c | The 6502 Manic Miner compiled code -| mmm.c | The Apple II emulator (all 403 lines of it ;) +| mmm.c | The Apple II emulator (around 400 lines :) # Building the code The CMakeLists.txt file works for my installation. This is my note at the top which sums up my feelings and frustrations. diff --git a/src/mmm/src/6502.h b/src/mmm/src/6502.h index d635909..bc038dc 100644 --- a/src/mmm/src/6502.h +++ b/src/mmm/src/6502.h @@ -11,7 +11,7 @@ struct MEMORY_REGION { uint8_t *memory; }; -/* RAM_BANK is */ +/* RAM contains an array of MEMORY_REGIONS which may (or not) be mapped into the 6502's 64K*/ typedef struct MEMORY_REGION RAM_BANK; struct RAM { RAM_BANK *ram_banks; @@ -119,10 +119,6 @@ void rom_add(ROMS *roms, uint8_t rom_num, uint32_t address, uint32_t length, uint8_t pages_init(PAGES *pages, uint16_t num_pages); void pages_map(PAGES *pages, uint32_t start_page, uint32_t num_pages, uint8_t *memory); -// Exposed so that HARTE tests can be loaded and checked -uint8_t read_from_memory(MACHINE *m, uint16_t address); -void write_to_memory(MACHINE *m, uint16_t address, uint8_t value); - // 1 time init void cpu_init(CPU *cpu); diff --git a/src/mmm/src/mmm.c b/src/mmm/src/mmm.c index 758a45a..95459b5 100644 --- a/src/mmm/src/mmm.c +++ b/src/mmm/src/mmm.c @@ -22,7 +22,8 @@ uint8_t RAM_IO[RAM_SIZE]; // 64K of IO port "mask" (0 = #define LOWSCR 0xC054 // Port that draw Hires from $2000 #define HISCR 0xC055 // Port that draws Hires from $4000 -// The start of a line of pixels (192 rows). (Add to active Hires page ie $2000 or $4000) +// The start of a line of pixels (192 rows) in HGR memory. +// (Add to active Hires page ie $2000 or $4000) uint16_t row_start[] = { 0x0000,0x0400,0x0800,0x0C00,0x1000,0x1400,0x1800,0x1C00, 0x0080,0x0480,0x0880,0x0C80,0x1080,0x1480,0x1880,0x1C80, @@ -74,14 +75,13 @@ SDL_Renderer *renderer; SDL_Surface *surface; SDL_Texture *texture; int screen_updated = TARGET_FPS; // Counter - at TARGET_FPS forces screen update -int active_page = 0x2000; // 0x2000 or 0x4000 - active hires memory page +int active_page = 0x4000; // 0x2000 or 0x4000 - active hires memory page // Global variables to emulate speaker clicks -#define AMPLITUDE 28000 #define SAMPLE_RATE 44100 -int audio_paused = 0; // Audio is paused (0) or playing (1) +int audio_paused = 1; // Audio is paused (1) or playing (0) int speaker_state = 0; // Tracks whether the speaker is in the "on" or "off" state -double frequency = 440.0; // Frequency in Hz (dynamically calculated ) +double frequency = 440.0; // Frequency in Hz (dynamically calculated) Uint64 last_toggle_time = 0; // Last time the speaker was toggled (in performance counter ticks) Uint64 frequency_ticks = 0; // Frequency of the performance counter @@ -146,44 +146,39 @@ void show_screen(uint16_t page) { // Loop through each row for (y = 0; y < 192; y++) { - uint32_t *p = &pixels[y * surface->w]; // Get the pointer to the start of the row in the SDL surface - int address = page + row_start[y]; + // Get the pointer to the start of the row in the SDL surface + uint32_t *p = &pixels[y * surface->w]; + // An index to "walk" the pixels in the surface int px = 0; + // Get the address where this row starts in HGR memory + int address = page + row_start[y]; - // Loop through every 2 bytes (40 iterations for each 192-pixel row) + // Loop through every 2 bytes (40 iterations for each 280-pixel row - 140 color pixels) for (int x = 0; x < 40; x += 2) { - uint16_t col = (RAM_MAIN[address + x + 1] << 8) | RAM_MAIN[address + x]; // Combine two bytes into a 16-bit value + // Combine two bytes into a 16-bit value for ease of extracting pixels + uint16_t col = (RAM_MAIN[address + x + 1] << 8) | RAM_MAIN[address + x]; - // Extract pixels and high bits - int p1 = (col & 0b0000000000000001) << 1 | (col & 0b0000000000000010) >> 1; - int p2 = (col & 0b0000000000000100) >> 1 | (col & 0b0000000000001000) >> 3; - int p3 = (col & 0b0000000000010000) >> 3 | (col & 0b0000000000100000) >> 5; - int p4 = (col & 0b0000000001000000) >> 5 | (col & 0b0000000100000000) >> 8; - int p5 = (col & 0b0000001000000000) >> 8 | (col & 0b0000010000000000) >> 10; - int p6 = (col & 0b0000100000000000) >> 10 | (col & 0b0001000000000000) >> 12; - int p7 = (col & 0b0010000000000000) >> 12 | (col & 0b0100000000000000) >> 14; - - // High bits for color adjustment + // Extract the phase bits int ph1 = (col & 0b0000000010000000) >> 5; int ph2 = (col & 0b1000000000000000) >> 13; - // Precompute color indices for each pixel - int idx1 = p1 + ph1; - int idx2 = p2 + ph1; - int idx3 = p3 + ph1; - int idx4 = p4 + ph1; - int idx5 = p5 + ph2; - int idx6 = p6 + ph2; - int idx7 = p7 + ph2; + // Extract pixels and offset for phase bits + int p1 = ph1 + ((col & 0b0000000000000001) << 1 | (col & 0b0000000000000010) >> 1 ); + int p2 = ph1 + ((col & 0b0000000000000100) >> 1 | (col & 0b0000000000001000) >> 3 ); + int p3 = ph1 + ((col & 0b0000000000010000) >> 3 | (col & 0b0000000000100000) >> 5 ); + int p4 = ph1 + ((col & 0b0000000001000000) >> 5 | (col & 0b0000000100000000) >> 8 ); + int p5 = ph2 + ((col & 0b0000001000000000) >> 8 | (col & 0b0000010000000000) >> 10); + int p6 = ph2 + ((col & 0b0000100000000000) >> 10 | (col & 0b0001000000000000) >> 12); + int p7 = ph2 + ((col & 0b0010000000000000) >> 12 | (col & 0b0100000000000000) >> 14); - // Access the surface's pixels and set the pixel value from the palette - p[px++] = SDL_MapRGB(surface->format, palette[idx1].c[0], palette[idx1].c[1], palette[idx1].c[2]); - p[px++] = SDL_MapRGB(surface->format, palette[idx2].c[0], palette[idx2].c[1], palette[idx2].c[2]); - p[px++] = SDL_MapRGB(surface->format, palette[idx3].c[0], palette[idx3].c[1], palette[idx3].c[2]); - p[px++] = SDL_MapRGB(surface->format, palette[idx4].c[0], palette[idx4].c[1], palette[idx4].c[2]); - p[px++] = SDL_MapRGB(surface->format, palette[idx5].c[0], palette[idx5].c[1], palette[idx5].c[2]); - p[px++] = SDL_MapRGB(surface->format, palette[idx6].c[0], palette[idx6].c[1], palette[idx6].c[2]); - p[px++] = SDL_MapRGB(surface->format, palette[idx7].c[0], palette[idx7].c[1], palette[idx7].c[2]); + // Set the pixel value from the palette + p[px++] = SDL_MapRGB(surface->format, palette[p1].c[0], palette[p1].c[1], palette[p1].c[2]); + p[px++] = SDL_MapRGB(surface->format, palette[p2].c[0], palette[p2].c[1], palette[p2].c[2]); + p[px++] = SDL_MapRGB(surface->format, palette[p3].c[0], palette[p3].c[1], palette[p3].c[2]); + p[px++] = SDL_MapRGB(surface->format, palette[p4].c[0], palette[p4].c[1], palette[p4].c[2]); + p[px++] = SDL_MapRGB(surface->format, palette[p5].c[0], palette[p5].c[1], palette[p5].c[2]); + p[px++] = SDL_MapRGB(surface->format, palette[p6].c[0], palette[p6].c[1], palette[p6].c[2]); + p[px++] = SDL_MapRGB(surface->format, palette[p7].c[0], palette[p7].c[1], palette[p7].c[2]); } } @@ -196,7 +191,7 @@ void show_screen(uint16_t page) { screen_updated = 0; } -// Note the actual program counter and value read from RAM on a read +// Handle the Apple II ports used by Manic Miner uint8_t io_read_callback(MACHINE *m, uint16_t address) { switch(address) { case KBDSTRB: @@ -217,7 +212,7 @@ uint8_t io_read_callback(MACHINE *m, uint16_t address) { return m->read_pages.pages[address / PAGE_SIZE].memory[address % PAGE_SIZE]; } -// Note the actual program counter and value written to RAM on a write +// Writing to these ports is the same as reading from them void io_write_callback(MACHINE *m, uint16_t address, uint8_t value) { io_read_callback(m, address); } @@ -275,7 +270,7 @@ int AppleII_configure(MACHINE *m) { } // Set up SDL graphics and Audio -int initSDL() { +int init_sdl() { // Initialize SDL with video and audio if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) { printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); @@ -308,7 +303,7 @@ int initSDL() { return 0; } - // Now the Audio + // Now init the Audio SDL_AudioSpec wanted_spec; SDL_AudioSpec obtained_spec; @@ -341,7 +336,7 @@ int main(int argc, char* argv[]) { Uint64 start_time, end_time; Uint64 ticks_per_clock_cycl = frequency_ticks / CPU_FREQUENCY; // Ticks per microsecond - if(!initSDL()) { + if(!init_sdl()) { return 1; } @@ -381,7 +376,7 @@ int main(int argc, char* argv[]) { // When the speaker is not being toggled, it needs to turn off end_time = SDL_GetPerformanceCounter(); - if(audio_paused && end_time - last_toggle_time > (frequency_ticks / 8)) { + if(!audio_paused && end_time - last_toggle_time > (frequency_ticks / 8)) { audio_paused = 1; SDL_PauseAudio(1); end_time = SDL_GetPerformanceCounter();