kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
some ga impl, need to test it
rodzic
f3b6610a56
commit
552f9b4ff4
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
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
|
||||
};
|
||||
|
|
|
@ -7,9 +7,8 @@ extern "C" {
|
|||
}
|
||||
#include "keyboard_osd.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "cpc.h"
|
||||
}
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef USE_VGA
|
||||
|
|
Ładowanie…
Reference in New Issue