kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
buggy video still, crashes after a while
rodzic
4a399d7763
commit
bd3f4ec1b1
|
@ -11,16 +11,25 @@ extern "C" {
|
|||
#include "platform_config.h"
|
||||
}
|
||||
#include "processor/Z80.h"
|
||||
#include "roms/rom464.h"
|
||||
#include "crtc.h"
|
||||
#include "ga.h"
|
||||
#include "roms/rom464.h"
|
||||
|
||||
#define WIDTH 320
|
||||
#define HEIGHT 200
|
||||
|
||||
#define CYCLES_PER_FRAME 19968
|
||||
#define NBLINES 312
|
||||
#define CYCLES_PER_STEP CYCLES_PER_FRAME/NBLINES
|
||||
|
||||
/*
|
||||
* Declarations of instances of the RAM, VRAM, processor and other required components.
|
||||
*/
|
||||
|
||||
char osROM[0x4000];
|
||||
char basicROM[0x4000];
|
||||
uint8_t RAM[0x10000]; // 64k
|
||||
uint8_t bitstream[0x4000]; // 16k video ram to be used by PIO.
|
||||
unsigned char* bitstream = 0; // 16k video ram to be used by PIO.
|
||||
static Z80 CPU;
|
||||
bool interruptGenerated = false;
|
||||
|
||||
|
@ -28,53 +37,59 @@ bool interruptGenerated = false;
|
|||
/*
|
||||
* Implementations of system-specific emuapi Init, Step etc. functions.
|
||||
*/
|
||||
#define CYCLES_PER_FRAME 80000
|
||||
|
||||
#define NBLINES (1) //(48+192+56+16) //(32+256+32)
|
||||
#define CYCLES_PER_STEP (CYCLES_PER_FRAME/NBLINES)
|
||||
|
||||
void cpc_Init(void)
|
||||
{
|
||||
|
||||
for(int i = 0; i < PALETTE_SIZE; i++)
|
||||
{
|
||||
// R, G and B are not absolute RGB, they are percentegaes. TODO change that.
|
||||
emu_SetPaletteEntry(palette[i].R, palette[i].G, palette[i].B, i);
|
||||
}
|
||||
if (bitstream == 0) bitstream = (unsigned char *)emu_Malloc(WIDTH*HEIGHT);
|
||||
|
||||
//memset(RAM, 0, sizeof(RAM));
|
||||
ResetZ80(&CPU, CYCLES_PER_FRAME);
|
||||
memset(RAM, 0, sizeof(RAM));
|
||||
}
|
||||
|
||||
//ResetZ80(&CPU, CYCLES_PER_FRAME);
|
||||
void cpc_Start(char* filename)
|
||||
{
|
||||
|
||||
// Interrupts disabled, PC=0, enable low rom, disable high rom, gate array scanline counter = 0, write 0xC0 into GA.
|
||||
// set memory to 0.
|
||||
|
||||
CPU.IFF = 0;
|
||||
CPU.PC.W = 0x0000;
|
||||
CPU.IRequest = INT_NONE;
|
||||
gaConfig.lowerROMEnable = true;
|
||||
gaConfig.upperROMEnable = false;
|
||||
gaConfig.interruptCounter = 0;
|
||||
writeGA(0xC0);
|
||||
// writeGA(0x89);
|
||||
// CPU.PC.W = 0x580;
|
||||
}
|
||||
|
||||
void cpc_Step(void)
|
||||
{
|
||||
// printf("Enter step\n");
|
||||
|
||||
// TODO I don't think I am actually loading the ROM and having the CPU start executing w/e's there.
|
||||
|
||||
for(int i = 0; i<CYCLES_PER_FRAME; i++)
|
||||
{
|
||||
ExecZ80(&CPU, 1);
|
||||
|
||||
crtc_step();
|
||||
interruptGenerated = ga_step();
|
||||
if(interruptGenerated)
|
||||
{
|
||||
CPU.IRequest = INT_RST38;
|
||||
gaConfig.interruptCounter &= 0x1F;
|
||||
// RunZ80(&CPU);
|
||||
//printf("Current program counter: %d \n", CPU.PC.W);
|
||||
for(int i = 0; i < NBLINES; i++)
|
||||
{
|
||||
ExecZ80(&CPU, CYCLES_PER_STEP);
|
||||
for(int j = 0; j < CYCLES_PER_STEP; j++)
|
||||
{
|
||||
crtc_step();
|
||||
interruptGenerated = ga_step();
|
||||
if(interruptGenerated)
|
||||
{
|
||||
printf("Interrupting! Jumping to \n");
|
||||
IntZ80(&CPU, INT_IRQ);
|
||||
gaConfig.interruptCounter &= 0x1F;
|
||||
}
|
||||
}
|
||||
emu_DrawLine8(bitstream, WIDTH, HEIGHT, i);
|
||||
//printf("index %d: %c \n", i, bitstream + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU.IRequest = INT_NONE;
|
||||
}
|
||||
// printf("Executed %d steps in hardware\n", 256);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cpc_Start(char* filename)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void cpc_Input(int bClick)
|
||||
|
@ -82,11 +97,6 @@ void cpc_Input(int bClick)
|
|||
|
||||
}
|
||||
|
||||
void displayScreen()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* System-specific implementations of the Z80 instructions required by the portable Z80 emulator.
|
||||
*/
|
||||
|
@ -107,6 +117,19 @@ void OutZ80(word Port, byte Value)
|
|||
}
|
||||
}
|
||||
|
||||
// word LoopZ80(Z80 *R)
|
||||
// {
|
||||
|
||||
// if(interruptGenerated)
|
||||
// {
|
||||
// return INT_IRQ;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return INT_NONE;
|
||||
// }
|
||||
// }
|
||||
|
||||
byte InZ80(word Port)
|
||||
{
|
||||
if(!(Port & 0x4000)) return readCRTC(Port); // The CRTC is selected when bit 14 is set to 0.
|
||||
|
@ -119,6 +142,8 @@ byte InZ80(word Port)
|
|||
void WrZ80(word Addr, byte Value)
|
||||
{
|
||||
RAM[Addr] = Value;
|
||||
|
||||
//printf("Write %x at %x \n", Value, Addr);
|
||||
}
|
||||
|
||||
void PatchZ80(Z80 *R)
|
||||
|
@ -130,17 +155,17 @@ byte RdZ80(word Addr)
|
|||
{
|
||||
if(Addr <= LOWER_ROM_END && gaConfig.lowerROMEnable)
|
||||
{
|
||||
// printf("Reading from the OS ROM.\n");
|
||||
// printf("At program counter %x, Z80 read from address %x in OS ROM\n", CPU.PC.W, Addr);
|
||||
return gb_rom_464_0[Addr];
|
||||
}
|
||||
else if(Addr >= UPPER_ROM_BEGIN && gaConfig.upperROMEnable)
|
||||
{
|
||||
// printf("Reading from BASIC's ROM.\n");
|
||||
// printf("At program counter %x, Z80 read from address %x in BASIC ROM\n", CPU.PC.W, Addr);
|
||||
return gb_rom_464_1[Addr - 0xC000];
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("Reading from RAM.\n");
|
||||
// printf("At program counter %x, Z80 read from address %x in RAM\n", CPU.PC.W, Addr);
|
||||
return RAM[Addr];
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
#endif
|
||||
|
||||
extern uint8_t RAM[0x10000];
|
||||
extern uint8_t bitstream[0x4000];
|
||||
extern unsigned char* bitstream;
|
||||
extern struct GAConfig gaConfig;
|
||||
|
||||
extern void cpc_Init(void);
|
||||
|
|
|
@ -41,29 +41,30 @@ void crtc_step()
|
|||
horizontalCount = 0;
|
||||
scanlineCount++;
|
||||
// printf("Resetting horizontal counter!\n");
|
||||
|
||||
if(scanlineCount > registers[9])
|
||||
{
|
||||
// The counter for Maximum Raster Address is equal to it.
|
||||
// The height of a character is 8 rasters, so when we reach 8 rasters we increment the char line count.
|
||||
|
||||
scanlineCount = 0;
|
||||
characterLineCount++;
|
||||
//printf("characterLineCount: %d \n", characterLineCount);
|
||||
if(characterLineCount > registers[4])
|
||||
{
|
||||
// The vertical counter reaches the Vertical Total register.
|
||||
characterLineCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(characterLineCount == 0)
|
||||
{
|
||||
memoryAddr = ((uint16_t) registers[12] << 8) | registers[13];
|
||||
}
|
||||
}
|
||||
|
||||
if(scanlineCount > registers[9])
|
||||
{
|
||||
// The counter for Maximum Raster Address is equal to it.
|
||||
// The height of a character is 8 rasters, so when we reach 8 rasters we increment the char line count.
|
||||
scanlineCount = 0;
|
||||
characterLineCount++;
|
||||
//printf("characterLineCount: %d \n", characterLineCount);
|
||||
// printf("Resetting scanline counter!\n");
|
||||
}
|
||||
// printf("Scanline count: %d \n", scanlineCount);
|
||||
|
||||
if(characterLineCount > registers[4])
|
||||
{
|
||||
// The vertical counter reaches the Vertical Total register.
|
||||
characterLineCount = 0;
|
||||
}
|
||||
|
||||
if(horizontalCount == 0 && characterLineCount == 0)
|
||||
{
|
||||
memoryAddr = ((uint16_t) registers[12] << 8) | registers[13];
|
||||
// printf("memoryAddr update! New value: %x \n", memoryAddr);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t crtc_generateAddress()
|
||||
|
@ -77,10 +78,16 @@ uint16_t crtc_generateAddress()
|
|||
uint16_t elevenToThirteenBits = (scanlineCount & 0b0000000000000111) << 11;
|
||||
uint16_t fourteenFifteenBits = (memoryAddr & 0b0011000000000000) << 2;
|
||||
//printf("memoryAddr: %x \n calculatedAddr: %x \n", memoryAddr, fourteenFifteenBits | elevenToThirteenBits | firstTenBits);
|
||||
|
||||
|
||||
// printf("Address generated by the crtc: %x \n", fourteenFifteenBits | elevenToThirteenBits | firstTenBits);
|
||||
return fourteenFifteenBits | elevenToThirteenBits | firstTenBits;
|
||||
}
|
||||
|
||||
bool isWithinDisplay()
|
||||
{
|
||||
return horizontalCount < registers[0] && scanlineCount < registers[6];
|
||||
}
|
||||
|
||||
bool isHSyncActive()
|
||||
{
|
||||
// HSYNC is active if the horizontal counter is in the
|
||||
|
@ -93,10 +100,8 @@ bool isVSyncActive()
|
|||
{
|
||||
int8_t characterHeight = (int8_t) registers[9] + 1;
|
||||
int8_t characterLinesCounted = (int8_t) characterLineCount - registers[7];
|
||||
// printf("characterHeight: %d \ncharacterLineCount: %d \nscanlineCount: %d \n", characterHeight, characterLineCount, scanlineCount);
|
||||
// printf("isVSyncActive value calculated: %d \n", characterHeight * characterLinesCounted + scanlineCount);
|
||||
return characterHeight * characterLineCount + (int8_t) scanlineCount >= 0 &&
|
||||
characterHeight * characterLineCount + (int8_t) scanlineCount <= 128;
|
||||
return characterHeight * characterLineCount + (int8_t) scanlineCount >= 0 &&
|
||||
characterHeight * characterLineCount + (int8_t) scanlineCount <= 128;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ extern uint8_t verticalAdjustCount;
|
|||
|
||||
bool isHSyncActive();
|
||||
bool isVSyncActive();
|
||||
bool isWithinDisplay();
|
||||
uint16_t crtc_generateAddress();
|
||||
void crtc_step();
|
||||
void writeCRTC(unsigned short address, uint8_t value);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
/* Title */
|
||||
#define TITLE " Amstrad CPC Emulator"
|
||||
#define ROMSDIR "cpc"
|
||||
#define ROMSDIR "roms"
|
||||
|
||||
#define emu_Init(ROM) {cpc_Init(); cpc_Start(ROM);}
|
||||
#define emu_Step(x) {cpc_Step();}
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
#include "pico/stdlib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ga.h"
|
||||
#include "crtc.h"
|
||||
#include "cpc.h"
|
||||
|
||||
|
||||
struct GAConfig gaConfig;
|
||||
|
||||
/**
|
||||
|
@ -13,38 +15,38 @@ struct GAConfig gaConfig;
|
|||
* 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
|
||||
{128, 128, 128}, // White
|
||||
{128, 128, 128}, // White
|
||||
{0, 255, 128}, // Sea Green
|
||||
{255, 255, 128}, // Pastel Yellow
|
||||
{0, 0, 128}, // Blue
|
||||
{255, 0, 128}, // Purple
|
||||
{0, 128, 128}, // Cyan
|
||||
{255, 128, 128}, // Pink
|
||||
{255, 0, 128}, // Purple
|
||||
{255, 255, 128}, // Pastel Yellow
|
||||
{255, 255, 0}, // Bright Yellow
|
||||
{255, 255, 255}, // Bright White
|
||||
{255, 0, 0}, // Bright Red
|
||||
{255, 0, 255}, // Bright Magenta
|
||||
{255, 128, 0}, // Orange
|
||||
{255, 128, 255}, // Pastel Magenta
|
||||
{0, 0, 128}, // Blue
|
||||
{0, 255, 128}, // Sea Green
|
||||
{0, 255, 0}, // Bright Green
|
||||
{0, 255, 255}, // 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
|
||||
{0, 0, 255}, // Bright Blue
|
||||
{0, 128, 0}, // Green
|
||||
{0, 128, 255}, // Sky Blue
|
||||
{128, 0, 128}, // Magenta
|
||||
{128, 255, 128}, // Pastel Green
|
||||
{128, 255, 0}, // Lime
|
||||
{128, 255, 255}, // Pastel Cyan
|
||||
{128, 0, 0}, // Red
|
||||
{128, 0, 255}, // Mauve
|
||||
{128, 128, 0}, // Yellow
|
||||
{128, 128, 255} // Pastel Blue
|
||||
};
|
||||
|
||||
bool updateInterrupts()
|
||||
|
@ -85,48 +87,98 @@ bool updateInterrupts()
|
|||
return interrupt_generated;
|
||||
}
|
||||
|
||||
char convertPixelToVGA(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
return VGA_RGB(r,g,b);
|
||||
}
|
||||
|
||||
void addressToPixels()
|
||||
{
|
||||
// When HSYNC is active Gate-Array outputs the palette colour black
|
||||
if(gaConfig.hsyncActive)
|
||||
{
|
||||
*bitstream = convertPixelToVGA(gaConfig.penColours[19].R,
|
||||
gaConfig.penColours[19].G,
|
||||
gaConfig.penColours[19].B);
|
||||
*bitstream++;
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
uint16_t address = crtc_generateAddress() + i;
|
||||
//printf(" address from CRTC: %x \nRAM data: %x \n", address, RAM[address]);
|
||||
uint8_t encodedByte = RAM[address];
|
||||
if(RAM[address] != 0 && address >= 0xC000)
|
||||
{
|
||||
printf("CRTC generated addr: %x \nRAM[address]: %x \n", address, encodedByte);
|
||||
uint8_t pixel0, pixel1, pixel2, pixel3;
|
||||
uint8_t* pixels = (uint8_t*) calloc(4, 8*sizeof(uint8_t));
|
||||
// if(address >= 0xC000)
|
||||
// {
|
||||
// printf("CRTC generated addr: %x \nRAM[address]: %x \n", address, encodedByte);
|
||||
switch(gaConfig.screenMode)
|
||||
{
|
||||
case 0:
|
||||
bitstream[address - 0xC000] = (encodedByte & 0x80) >> 7 |
|
||||
(encodedByte & 0x08) >> 2 |
|
||||
(encodedByte & 0x20) >> 3 |
|
||||
(encodedByte & 0x02) << 2;
|
||||
bitstream[address + 1 - 0xC000] = (encodedByte & 0x40) >> 6 |
|
||||
(encodedByte & 0x04) >> 1 |
|
||||
(encodedByte & 0x10) >> 2 |
|
||||
(encodedByte & 0x01) << 3;
|
||||
pixel0 = (encodedByte & 0x80) >> 7 |
|
||||
(encodedByte & 0x08) >> 2 |
|
||||
(encodedByte & 0x20) >> 3 |
|
||||
(encodedByte & 0x02) << 2;
|
||||
pixel1 = (encodedByte & 0x40) >> 6 |
|
||||
(encodedByte & 0x04) >> 1 |
|
||||
(encodedByte & 0x10) >> 2 |
|
||||
(encodedByte & 0x01) << 3;
|
||||
pixels[0] = pixel0;
|
||||
pixels[1] = pixel1;
|
||||
|
||||
|
||||
// TODO may not be correct, needs testing.
|
||||
break;
|
||||
case 1:
|
||||
bitstream[address - 0xC000] = (encodedByte & 0x80) >> 7 |
|
||||
(encodedByte & 0x08) >> 2;
|
||||
bitstream[address + 1 - 0xC000] = (encodedByte & 0x40) >> 6 |
|
||||
(encodedByte & 0x04) >> 1;
|
||||
bitstream[address + 2 - 0xC000] = (encodedByte & 0x02) |
|
||||
(encodedByte & 0x20) >> 5;
|
||||
bitstream[address + 3 - 0xC000] = (encodedByte & 0x10) >> 4 |
|
||||
(encodedByte & 0x01) << 1;
|
||||
break;
|
||||
case 2:
|
||||
for (int j = 0; j < 8; j++)
|
||||
// bitstream[address - 0xC000]
|
||||
// bitstream[address + 1 - 0xC000]
|
||||
// need to consider each color for the 2 pixels
|
||||
for(int pixelIdx = 0; pixelIdx < 2; pixelIdx++)
|
||||
{
|
||||
bitstream[address + j - 0xC000] = (encodedByte >> 7 - j) & 1;
|
||||
for(int color = 0; color < 4; color++)
|
||||
{
|
||||
bitstream[address + color - 0xC000] = convertPixelToVGA(gaConfig.penColours[pixels[pixelIdx]].R,
|
||||
gaConfig.penColours[pixels[pixelIdx]].G,
|
||||
gaConfig.penColours[pixels[pixelIdx]].B);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
pixel0 = (encodedByte & 0x80) >> 7 |
|
||||
(encodedByte & 0x08) >> 2;
|
||||
pixel1 = (encodedByte & 0x40) >> 6 |
|
||||
(encodedByte & 0x04) >> 1;
|
||||
pixel2 = (encodedByte & 0x02) |
|
||||
(encodedByte & 0x20) >> 5;
|
||||
pixel3 = (encodedByte & 0x10) >> 4 |
|
||||
(encodedByte & 0x01) << 1;
|
||||
pixels[0] = pixel0;
|
||||
pixels[1] = pixel1;
|
||||
pixels[2] = pixel2;
|
||||
pixels[3] = pixel3;
|
||||
|
||||
for(int pixelIdx = 0; pixelIdx < 4; pixelIdx++)
|
||||
{
|
||||
for(int color = 0; color < 2; color++)
|
||||
{
|
||||
bitstream[address + color - 0xC000] = convertPixelToVGA(gaConfig.penColours[pixels[pixelIdx]].R,
|
||||
gaConfig.penColours[pixels[pixelIdx]].G,
|
||||
gaConfig.penColours[pixels[pixelIdx]].B);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
uint8_t pixel;
|
||||
for (int color = 0; color < 8; color++)
|
||||
{
|
||||
pixel = (encodedByte >> 7 - color) & 1;
|
||||
bitstream[address + color - 0xC000] = convertPixelToVGA(gaConfig.penColours[pixel].R,
|
||||
gaConfig.penColours[pixel].G,
|
||||
gaConfig.penColours[pixel].B);
|
||||
}
|
||||
break;
|
||||
// }
|
||||
}
|
||||
|
||||
free(pixels);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +186,9 @@ bool ga_step()
|
|||
{
|
||||
// TODO add proper GA responses to hsync and vsync signals.
|
||||
bool interruptGenerated = updateInterrupts();
|
||||
addressToPixels();
|
||||
// printf("Did the GA generate an interrupt? %d \n Interrupt counter: %d", interruptGenerated, gaConfig.interruptCounter);
|
||||
if(memoryAddr != 0)
|
||||
addressToPixels();
|
||||
|
||||
gaConfig.hsyncActive = isHSyncActive();
|
||||
gaConfig.vsyncActive = isVSyncActive();
|
||||
|
@ -166,9 +220,11 @@ void selectPenColour(uint8_t value)
|
|||
|
||||
void ROMMgmtAndScreenCfg(uint8_t value)
|
||||
{
|
||||
// Screen mode config, dictated by the least significant 2 bits.
|
||||
if(!gaConfig.hsyncActive)
|
||||
|
||||
if(!gaConfig.hsyncActive && isHSyncActive())
|
||||
{
|
||||
// Screen mode config, dictated by the least significant 2 bits.
|
||||
// Effective at next line.
|
||||
switch(value & 3)
|
||||
{
|
||||
case 0b00:
|
||||
|
@ -187,6 +243,7 @@ void ROMMgmtAndScreenCfg(uint8_t value)
|
|||
// mode 3, unused.
|
||||
break;
|
||||
}
|
||||
printf("Updated screen mode to mode %d", gaConfig.screenMode);
|
||||
}
|
||||
|
||||
// ROM enable flags.
|
||||
|
|
|
@ -13,6 +13,7 @@ void selectPenColour(uint8_t value);
|
|||
void romBanking(uint8_t value);
|
||||
|
||||
#define PEN_NUMBER 4 // Mode 0 has 16 pens, mode 1 has 4 pens and mode 2 has 2 pens.
|
||||
#define VGA_RGB(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
|
||||
|
||||
struct RGB {
|
||||
uint8_t R, G, B;
|
||||
|
|
|
@ -53,16 +53,15 @@ int main(void) {
|
|||
tft.begin();
|
||||
#endif
|
||||
emu_init();
|
||||
toggleMenu(false); // ####################################
|
||||
while (true) {
|
||||
if (menuActive()) {
|
||||
uint16_t bClick = emu_DebounceLocalKeys();
|
||||
int action = handleMenu(bClick);
|
||||
int action = ACTION_RUNTFT; //handleMenu(bClick);
|
||||
char * filename = menuSelection();
|
||||
if (action == ACTION_RUNTFT) {
|
||||
toggleMenu(false);
|
||||
emu_Init(filename);
|
||||
emu_start();
|
||||
emu_Init(filename);
|
||||
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
|
||||
tft.startDMA();
|
||||
struct repeating_timer timer;
|
||||
|
@ -71,11 +70,8 @@ int main(void) {
|
|||
tft.waitSync();
|
||||
}
|
||||
else {
|
||||
// tft.clear(VGA_RGB(200,0,0));
|
||||
emu_Step();
|
||||
emu_DrawScreen(bitstream, 320, 200, 1);
|
||||
emu_Step();
|
||||
tft.waitSync();
|
||||
// tft.clear(VGA_RGB(250,0,0));
|
||||
}
|
||||
//int c = getchar_timeout_us(0);
|
||||
//switch (c) {
|
||||
|
|
|
@ -699,7 +699,9 @@ word RunZ80(Z80 *R)
|
|||
if(!DebugZ80(R)) return(R->PC.W);
|
||||
#endif
|
||||
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
|
||||
R->ICount-=Cycles[I];
|
||||
|
||||
switch(I)
|
||||
|
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Ładowanie…
Reference in New Issue