diff --git a/MCUME_pico/picocpc/cpc.cpp b/MCUME_pico/picocpc/cpc.cpp index d8498ff..297923f 100644 --- a/MCUME_pico/picocpc/cpc.cpp +++ b/MCUME_pico/picocpc/cpc.cpp @@ -1,49 +1,67 @@ +#include "pico.h" +#include "pico/stdlib.h" #include "processor/Z80.h" #include "roms/rom464.h" + +extern "C" { #include "emuapi.h" +#include "platform_config.h" +} + #include "crtc.h" #include "ga.h" /* - * Declarations of the RAM, VRAM, processor instances. + * Declarations of instances of the RAM, VRAM, processor and other required components. */ -static byte z80RAM[0x10000]; // 64k -static byte screenRAM[0x4000]; // 16k + +static byte ram[0x10000]; // 64k +static byte bitstream[0x4000]; // 16k video ram to be used by PIO. static Z80 cpu; +extern struct GA_Config ga_config; /* - * Implementation of cpc.h which is used by emuapi.h to define emu_Init() etc. + * Implementations of system-specific emuapi Init, Step etc. functions. */ void cpc_Init(void) { - return; + } -void cpc_Step() +void cpc_Step(void) { - return; + } void cpc_Start(char* filename) { - return; + } void cpc_Input(int bClick) { - return; + } /* - * The implementations of the Z80 instructions required by the portable Z80 emulator. - * These implementations are system-specific. + * System-specific implementations of the Z80 instructions required by the portable Z80 emulator. */ + void OutZ80(register word Port, register byte Value) { - if(!(Port & 0x8000)) write_ga(Port, Value); // The Gate Array is selected when bit 15 is set to 0. + if(!(Port & 0x8000)) write_ga(Value); // The Gate Array is selected when bit 15 is set to 0. if(!(Port & 0x4000)) write_crtc(Port, Value); // The CRTC is selected when bit 14 is set to 0. - if(!(Port & 0x2000)) ; // upper rom bank number. ROM banking needs to be done regardless of CPC model + if(!(Port & 0x2000)) + { + // upper rom bank number. ROM banking needs to be done regardless of CPC model + // The Upper ROM Bank Number (in range of 0x00..0xFF) to be mapped to memory at 0xC000..0xFFFF + + // byte req_bank_number = Value & 15; + // if(ga_config.upper_rom_enable) + // { + // } + } } byte InZ80(register word Port) @@ -52,28 +70,26 @@ byte InZ80(register word Port) return 0xFF; } -#define RAM_BASE 0x4000 // The ROM takes up 0x0000-0x4000. From 0x4000-0x10000 is the RAM. +#define LOWER_ROM_END 0x4000 +#define UPPER_ROM_BEGIN 0xC000 -/** - * Write the byte Value into the address Addr. If Addr is less than RAM_BASE, - * then we do not write anything as it would be written into the ROM. -*/ void WrZ80(register word Addr, register byte Value) { - if(Addr >= RAM_BASE) - { - z80RAM[Addr - RAM_BASE] = Value; - } + ram[Addr] = Value; } byte RdZ80(register word Addr) { - if(Addr < RAM_BASE) + if(Addr <= LOWER_ROM_END && ga_config.lower_rom_enable) { return gb_rom_464_0[Addr]; } + else if(Addr >= UPPER_ROM_BEGIN && ga_config.upper_rom_enable) + { + return gb_rom_464_1[Addr]; + } else { - return z80RAM[Addr - RAM_BASE]; + return ram[Addr]; } } \ No newline at end of file diff --git a/MCUME_pico/picocpc/emuapi.h b/MCUME_pico/picocpc/emuapi.h index 43a215c..0594dc4 100644 --- a/MCUME_pico/picocpc/emuapi.h +++ b/MCUME_pico/picocpc/emuapi.h @@ -13,7 +13,7 @@ #define emu_Step(x) {cpc_Step();} #define emu_Input(x) {cpc_Input(x);} -#define PALETTE_SIZE 27 +#define PALETTE_SIZE 32 #define VID_FRAME_SKIP 0x0 #define TFT_VBUFFER_YCROP 0 #define TFT_VUBFFER_YCROP 0 diff --git a/MCUME_pico/picocpc/ga.cpp b/MCUME_pico/picocpc/ga.cpp index e7dae5b..bfa49bd 100644 --- a/MCUME_pico/picocpc/ga.cpp +++ b/MCUME_pico/picocpc/ga.cpp @@ -11,53 +11,122 @@ #include "pico/stdlib.h" #include "ga.h" -extern struct Registers regs; +struct GA_Config ga_config; +/** + * Some of these colours are duplicates, because select_pen_colour() uses the least significant + * 5 bits to index into this array, so the duplicates prevent out-of-bounds read. +*/ + +struct RGB Palette[32] = { + {50, 50, 50}, // White + {50, 50, 50}, // White + {0, 100, 50}, // Sea Green + {100, 100, 50}, // Pastel Yellow + {0, 0, 50}, // Blue + {100, 0, 50}, // Purple + {0, 50, 50}, // Cyan + {100, 50, 50}, // Pink + {100, 0, 50}, // Purple + {100, 100, 50}, // Pastel Yellow + {100, 100, 0}, // Bright Yellow + {100, 100, 100}, // Bright White + {100, 0, 0}, // Bright Red + {100, 0, 100}, // Bright Magenta + {100, 50, 0}, // Orange + {100, 50, 100}, // Pastel Magenta + {0, 0, 50}, // Blue + {0, 100, 50}, // Sea Green + {0, 100, 0}, // Bright Green + {0, 100, 100}, // Bright Cyan + {0, 0, 0}, // Black + {0, 0, 100}, // Bright Blue + {0, 50, 0}, // Green + {0, 50, 100}, // Sky Blue + {50, 0, 50}, // Magenta + {50, 100, 50}, // Pastel Green + {50, 100, 0}, // Lime + {50, 100, 100}, // Pastel Cyan + {50, 0, 0}, // Red + {50, 0, 100}, // Mauve + {50, 50, 0}, // Yellow + {50, 50, 100} // Pastel Blue +}; + + +void select_pen(register uint8_t value) +{ + switch(value >> 4) + { + case 0b01: + // Select border. + ga_config.pen_selected = 0x10; + break; + case 0b00: + // Bits 0-3 dictate the pen number + ga_config.pen_selected = value & 15; + break; + } +} + +void select_pen_colour(register uint8_t value) +{ + // Bits 0-4 of "value" specify the hardware colour number from the hardware colour palette. + // (i.e. which index into the Palette array of structs.) + ga_config.pen_colors[ga_config.pen_selected] = Palette[value & 31]; +} + +void do_rom_bank_screen_cfg(register uint8_t value) +{ + // Screen mode config, dictated by the least significant 2 bits. + switch(value & 3) + { + case 0b00: + // mode 0 + // ga_config.ScreenMode = 0; + break; + case 0b01: + // mode 1 + ga_config.screen_mode = 1; + break; + case 0b10: + // mode 2 + // ga_config.ScreenMode = 2; + break; + case 0b11: + // mode 3, unused. + break; + } + + // ROM enable flags. + if ((value >> 2) & 0b1) ga_config.lower_rom_enable = false; else ga_config.lower_rom_enable = true; + if ((value >> 3) & 0b1) ga_config.upper_rom_enable = false; else ga_config.upper_rom_enable = true; + + // Interrupt generation control. + if ((value >> 4) & 0b1) ga_config.interrupt_delay = true; else ga_config.interrupt_delay = false; +} /** Bit 7 Bit 6 Function * --0-- --0-- Select pen * --0-- --1-- Select colour of the selected pen * --1-- --0-- Select screen mode, ROM configuration and interrupt control - * --1-- --1-- RAM memory management (Note: This is not available on the CPC 464) + * --1-- --1-- RAM memory management */ -void write_ga(register uint16_t address, register uint8_t value) +void write_ga(register uint8_t value) { - switch(address >> 6) + switch(value >> 6) { - case 0x00: - select_pen(address, value); + case 0b00: + select_pen(value); break; - case 0x01: - select_pen_colour(address, value); + case 0b01: + select_pen_colour(value); break; - case 0x10: - rom_banking(address, value); + case 0b10: + do_rom_bank_screen_cfg(value); break; - case 0x11: - // This would be RAM banking but we are not concerned with that yet. + case 0b11: + // This would be RAM banking but it is not available on the CPC464. break; } } -// TODO delete address argument? -void select_pen(register uint16_t address, register uint8_t value) -{ - switch(value >> 4) - { - case 0x01: - // Select border. TODO implement - break; - case 0x00: - // Bits 0-3 dictate the pen number - regs.PaletteIndex = value >> 4; - } -} -void select_pen_colour(register uint16_t address, register uint8_t value) -{ - // Bits 4 to 0 specify the hardware colour number from the hardware colour palette. - regs.PaletteData[regs.PaletteIndex] = value & 0x000FFFFF; -} - -void rom_banking(register uint16_t address, register uint8_t value) -{ - return; -} diff --git a/MCUME_pico/picocpc/ga.h b/MCUME_pico/picocpc/ga.h index 0d1053f..12b95be 100644 --- a/MCUME_pico/picocpc/ga.h +++ b/MCUME_pico/picocpc/ga.h @@ -1,43 +1,20 @@ -void write_ga(register uint16_t address, register uint8_t value); -void select_pen(register uint16_t address, register uint8_t value); -void select_pen_colour(register uint16_t address, register uint8_t value); -void rom_banking(register uint16_t address, register uint8_t value); - -struct { unsigned char R,G,B;} Palette[27] = { - { 0, 0, 0}, // Black - { 0, 0, 128}, // Blue - { 0, 0, 255}, // Bright blue - { 128, 0, 0}, // Red - { 128, 0, 128}, // Magenta - { 128, 0, 255}, // Mauve - { 255, 0, 0}, // Bright Red - { 255, 0, 128}, // Purple - { 255, 0, 255}, // Bright Magenta - { 0, 128, 0}, // Green - { 0, 128, 128}, // Cyan - { 0, 128, 255}, // Sky Blue - { 128, 128, 0}, // Yellow - { 128, 128, 128}, // White - { 128, 128, 255}, // Pastel Blue - { 255, 128, 0}, // Orange - { 255, 128, 128}, // Pink - { 255, 128, 255}, // Pastel Magenta - { 0, 255, 0}, // Bright Green - { 0, 255, 128}, // Sea Green - { 0, 255, 255}, // Bright Cyan - { 128, 255, 0}, // Lime - { 128, 255, 128}, // Pastel Green - { 128, 255, 255}, // Pastel Cyan - { 255, 255, 0}, // Bright Yellow - { 255, 255, 128}, // Pastel Yellow - { 255, 255, 255}, // Bright White -}; +extern void write_ga(register uint8_t value); +void select_pen(register uint8_t value); +void select_pen_colour(register uint8_t value); +void rom_banking(register uint8_t value); #define PEN_NUMBER 4 // Mode 0 has 16 pens, mode 1 has 4 pens and mode 2 has 2 pens. -struct Registers { - uint8_t PaletteIndex = 0; - uint8_t PaletteData[PEN_NUMBER]; - uint8_t ScreenModeAndROMConfig = 0; - uint8_t RAMBanking = 0; // unused in CPC 464 -}; \ No newline at end of file +struct RGB { + uint8_t R, G, B; +}; + +struct GA_Config { + uint8_t pen_selected = 0; + RGB pen_colors[PEN_NUMBER]; + uint8_t screen_mode = 1; // 0 -> 160x200 16c; 1 -> 320x200 4c; 2 -> 640x200 2c; 3 (undocumented) -> 160x200 4c. + bool upper_rom_enable = false; + bool lower_rom_enable = false; + bool interrupt_delay = false; + uint8_t ram_banking = 0; // unused in CPC 464 +}; diff --git a/MCUME_pico/picocpc/picocpc.cpp b/MCUME_pico/picocpc/picocpc.cpp index 7104734..8d92d8f 100644 --- a/MCUME_pico/picocpc/picocpc.cpp +++ b/MCUME_pico/picocpc/picocpc.cpp @@ -7,9 +7,8 @@ extern "C" { } #include "keyboard_osd.h" -extern "C" { + #include "cpc.h" -} #include #ifdef USE_VGA