mirror of https://github.com/bsnes-emu/bsnes.git
Update to v101r05 release.
byuu says: Changelog: - 68K: fixed bug that affected BSR return address - VDP: added very preliminary emulation of planes A, B, W (W is entirely broken though) - VDP: added command/address stuff so you can write to VRAM, CRAM, VSRAM - VDP: added VRAM fill DMA I would be really surprised if any commercial games showed anything at all, so I'd probably recommend against wasting your time trying, unless you're really bored :P Also, I wanted to add: I am accepting patches\! So if anyone wants to look over the 68K core for bugs, that would save me untold amounts of time in the near future :D
This commit is contained in:
parent
1df2549d18
commit
ac2d0ba1cf
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "101.04";
|
||||
static const string Version = "101.05";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -15,6 +15,12 @@ auto CPU::boot() -> void {
|
|||
}
|
||||
|
||||
auto CPU::main() -> void {
|
||||
#if 0
|
||||
static file fp;
|
||||
if(!fp) fp.open({Path::user(), "Desktop/trace.log"}, file::mode::write);
|
||||
fp.print(pad(disassemble(r.pc), -60, ' '), " ", disassembleRegisters().replace("\n", " "), "\n");
|
||||
#endif
|
||||
|
||||
instruction();
|
||||
}
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ auto Interface::videoColors() -> uint32 {
|
|||
}
|
||||
|
||||
auto Interface::videoColor(uint32 color) -> uint64 {
|
||||
uint B = color.bits(0,2);
|
||||
uint R = color.bits(0,2);
|
||||
uint G = color.bits(3,5);
|
||||
uint R = color.bits(6,8);
|
||||
uint B = color.bits(6,8);
|
||||
|
||||
uint64 r = image::normalize(R, 3, 16);
|
||||
uint64 g = image::normalize(G, 3, 16);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
auto VDP::Background::scanline() -> void {
|
||||
}
|
||||
|
||||
auto VDP::Background::run(uint x, uint y) -> void {
|
||||
output.priority = 0;
|
||||
output.color = 0;
|
||||
|
||||
uint tileX = x >> 3;
|
||||
uint tileY = y >> 3;
|
||||
uint15 nametableAddress = io.nametableAddress;
|
||||
nametableAddress += (tileY << io.nametableWidth) + tileX;
|
||||
|
||||
uint16 tileAttributes = vdp.vram[nametableAddress];
|
||||
uint15 tileAddress = tileAttributes.bits(0,10) << 4;
|
||||
uint pixelX = (x & 7) ^ (tileAttributes.bit(11) ? 7 : 0);
|
||||
uint pixelY = (y & 7) ^ (tileAttributes.bit(12) ? 7 : 0);
|
||||
tileAddress += pixelY << 1 | pixelX >> 2;
|
||||
|
||||
uint16 tileData = vdp.vram[tileAddress];
|
||||
uint4 palette = tileData >> (((pixelX & 3) ^ 3) << 2);
|
||||
if(palette) {
|
||||
output.color = tileAttributes.bits(13,14) << 4 | palette;
|
||||
output.priority = tileAttributes.bit(15);
|
||||
}
|
||||
}
|
||||
|
||||
auto VDP::Background::power() -> void {
|
||||
}
|
||||
|
||||
auto VDP::Background::reset() -> void {
|
||||
memory::fill(&io, sizeof(IO));
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
auto VDP::dmaRun() -> void {
|
||||
if(!io.dmaEnable) return;
|
||||
if(!io.dmaActive) return;
|
||||
|
||||
if(io.dmaMode == 2) return dmaFillVRAM();
|
||||
}
|
||||
|
||||
auto VDP::dmaFillVRAM() -> void {
|
||||
auto address = io.address.bits(1,15);
|
||||
auto data = io.dmaFillWord;
|
||||
if(io.address.bit(0)) data = data >> 8 | data << 8;
|
||||
vram[address] = data;
|
||||
io.address += io.dataIncrement;
|
||||
|
||||
if(--io.dmaLength == 0) {
|
||||
io.dmaActive = false;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,25 @@
|
|||
//todo: does data mirroring occur for all VDP addresses; or just data/control ports?
|
||||
|
||||
auto VDP::readByte(uint24 addr) -> uint8 {
|
||||
return 0x00;
|
||||
auto data = readWord(addr & ~1);
|
||||
return data << 8 | data << 0;
|
||||
}
|
||||
|
||||
auto VDP::writeByte(uint24 addr, uint8 data) -> void {
|
||||
return writeWord(addr & ~1, data << 8 | data << 0);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto VDP::readWord(uint24 addr) -> uint16 {
|
||||
switch(addr & 0xc0001f) {
|
||||
|
||||
//data port
|
||||
case 0xc00000: case 0xc00002: {
|
||||
return readDataPort();
|
||||
}
|
||||
|
||||
//control port
|
||||
case 0xc00004: case 0xc00006: {
|
||||
return readControlPort();
|
||||
}
|
||||
|
@ -14,19 +29,19 @@ auto VDP::readWord(uint24 addr) -> uint16 {
|
|||
return 0x0000;
|
||||
}
|
||||
|
||||
auto VDP::writeByte(uint24 addr, uint8 data) -> void {
|
||||
//print("[VDP] ", hex(addr, 6L), "=", hex(data, 2L), "\n");
|
||||
}
|
||||
|
||||
auto VDP::writeWord(uint24 addr, uint16 data) -> void {
|
||||
//print("[VDP] ", hex(addr, 6L), "=", hex(data, 4L), "\n");
|
||||
|
||||
switch(addr & 0xc0001f) {
|
||||
|
||||
//data port
|
||||
case 0xc00000: case 0xc00002: {
|
||||
return writeDataPort(data);
|
||||
}
|
||||
|
||||
//control port
|
||||
case 0xc00004: case 0xc00006: {
|
||||
if(!data.bit(15)) return;
|
||||
return writeControlPort(data.bits(8,14), data.bits(0,7));
|
||||
return writeControlPort(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,15 +49,99 @@ auto VDP::writeWord(uint24 addr, uint16 data) -> void {
|
|||
|
||||
//
|
||||
|
||||
auto VDP::readDataPort() -> uint16 {
|
||||
io.commandPending = false;
|
||||
|
||||
//VRAM read
|
||||
if(io.command.bits(0,3) == 0) {
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
//VSRAM read
|
||||
if(io.command.bits(0,3) == 4) {
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
//CRAM read
|
||||
if(io.command.bits(0,3) == 8) {
|
||||
return 0x0000;
|
||||
}
|
||||
}
|
||||
|
||||
auto VDP::writeDataPort(uint16 data) -> void {
|
||||
io.commandPending = false;
|
||||
|
||||
//DMA VRAM fill
|
||||
if(io.command.bits(4,5) == 2) {
|
||||
io.dmaActive = true;
|
||||
io.dmaFillWord = data;
|
||||
return;
|
||||
}
|
||||
|
||||
//VRAM write
|
||||
if(io.command.bits(0,3) == 1) {
|
||||
auto address = io.address.bits(1,15);
|
||||
if(io.address.bit(0)) data = data >> 8 | data << 8;
|
||||
vram[address] = data;
|
||||
io.address += io.dataIncrement;
|
||||
return;
|
||||
}
|
||||
|
||||
//VSRAM write
|
||||
if(io.command.bits(0,3) == 5) {
|
||||
auto address = io.address.bits(1,6);
|
||||
if(address >= 40) return;
|
||||
//data format: ---- --yy yyyy yyyy
|
||||
vsram[address] = data.bits(0,9);
|
||||
io.address += io.dataIncrement;
|
||||
return;
|
||||
}
|
||||
|
||||
//CRAM write
|
||||
if(io.command.bits(0,3) == 3) {
|
||||
auto address = io.address.bits(1,6);
|
||||
//data format: ---- bbb- ggg- rrr-
|
||||
cram[address] = data.bits(1,3) << 0 | data.bits(5,7) << 3 | data.bits(9,11) << 6;
|
||||
io.address += io.dataIncrement;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto VDP::readControlPort() -> uint16 {
|
||||
io.commandPending = false;
|
||||
|
||||
uint16 result = 0b0011'0100'0000'0000;
|
||||
result |= io.dmaActive << 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto VDP::writeControlPort(uint7 addr, uint8 data) -> void {
|
||||
//print("[VDPC] ", hex(addr, 2L), "=", hex(data, 2L), "\n");
|
||||
auto VDP::writeControlPort(uint16 data) -> void {
|
||||
//print("[VDPC] ", hex(data, 4L), "\n");
|
||||
|
||||
switch(addr) {
|
||||
//command write (lo)
|
||||
if(io.commandPending) {
|
||||
io.commandPending = false;
|
||||
|
||||
io.command.bits(2,5) = data.bits(4,7);
|
||||
io.address.bits(14,15) = data.bits(0,1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//command write (hi)
|
||||
if(data.bits(14,15) != 2) {
|
||||
io.commandPending = true;
|
||||
|
||||
io.command.bits(0,1) = data.bits(14,15);
|
||||
io.address.bits(0,13) = data.bits(0,13);
|
||||
return;
|
||||
}
|
||||
|
||||
//register write (d13 is ignored)
|
||||
if(data.bits(14,15) == 2)
|
||||
switch(data.bits(8,12)) {
|
||||
|
||||
//mode register 1
|
||||
case 0x00: {
|
||||
|
@ -61,24 +160,27 @@ auto VDP::writeControlPort(uint7 addr, uint8 data) -> void {
|
|||
io.verticalBlankInterruptEnable = data.bit(5);
|
||||
io.displayEnable = data.bit(6);
|
||||
io.externalVRAM = data.bit(7);
|
||||
|
||||
if(!io.dmaEnable) io.command.bit(5) = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//plane A name table location
|
||||
case 0x02: {
|
||||
io.nametablePlaneA = data.bits(3,6);
|
||||
planeA.io.nametableAddress = data.bits(3,6) << 12;
|
||||
return;
|
||||
}
|
||||
|
||||
//window name table location
|
||||
case 0x03: {
|
||||
io.nametableWindow = data.bits(1,6);
|
||||
window.io.nametableAddress = data.bits(1,6) << 10;
|
||||
return;
|
||||
}
|
||||
|
||||
//plane B name table location
|
||||
case 0x04: {
|
||||
io.nametablePlaneB = data.bits(0,3);
|
||||
planeB.io.nametableAddress = data.bits(0,3) << 12;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -96,18 +198,7 @@ auto VDP::writeControlPort(uint7 addr, uint8 data) -> void {
|
|||
|
||||
//background color
|
||||
case 0x07: {
|
||||
io.backgroundIndex = data.bits(0,3);
|
||||
io.backgroundPalette = data.bits(4,5);
|
||||
return;
|
||||
}
|
||||
|
||||
//unused
|
||||
case 0x08: {
|
||||
return;
|
||||
}
|
||||
|
||||
//unused
|
||||
case 0x09: {
|
||||
io.backgroundColor = data.bits(0,5);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,30 +240,64 @@ auto VDP::writeControlPort(uint7 addr, uint8 data) -> void {
|
|||
return;
|
||||
}
|
||||
|
||||
//VRAM auto-increment value
|
||||
//data port auto-increment value
|
||||
case 0x0f: {
|
||||
io.vramAutoIncrement = data.bits(0,7);
|
||||
io.dataIncrement = data.bits(0,7);
|
||||
return;
|
||||
}
|
||||
|
||||
//plane size
|
||||
case 0x10: {
|
||||
io.horizontalPlaneSize = data.bits(0,1);
|
||||
io.verticalPlaneSize = data.bits(4,5);
|
||||
//0 = 32 tiles
|
||||
//1 = 64 tiles
|
||||
//2 = invalid (repeats first row for every scanline)
|
||||
//3 = 128 tiles
|
||||
static const uint shift[] = {5, 6, 0, 7};
|
||||
|
||||
planeA.io.nametableWidth = shift[data.bits(0,1)];
|
||||
window.io.nametableWidth = shift[data.bits(0,1)];
|
||||
planeB.io.nametableWidth = shift[data.bits(0,1)];
|
||||
|
||||
planeA.io.nametableHeight = shift[data.bits(4,5)];
|
||||
window.io.nametableHeight = shift[data.bits(4,5)];
|
||||
planeB.io.nametableHeight = shift[data.bits(4,5)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//window plane horizontal position
|
||||
case 0x11: {
|
||||
io.horizontalWindowPlanePosition = data.bits(0,4);
|
||||
io.horizontalWindowPlaneRight = data.bit(7);
|
||||
if(!data) {
|
||||
//disable
|
||||
io.windowHorizontalLo = ~0;
|
||||
io.windowHorizontalHi = ~0;
|
||||
} else if(data.bit(7) == 0) {
|
||||
//left
|
||||
io.windowHorizontalLo = 0;
|
||||
io.windowHorizontalHi = (data.bits(0,4) << 4) - 1;
|
||||
} else {
|
||||
//right
|
||||
io.windowHorizontalLo = (data.bits(0,4) << 4) - 1;
|
||||
io.windowHorizontalHi = ~0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//window plane vertical position
|
||||
case 0x12: {
|
||||
io.verticalWindowPlanePosition = data.bits(0,4);
|
||||
io.verticalWindowPlaneDown = data.bit(7);
|
||||
if(!data) {
|
||||
//disable
|
||||
io.windowVerticalLo = ~0;
|
||||
io.windowVerticalHi = ~0;
|
||||
} else if(data.bit(7) == 0) {
|
||||
//up
|
||||
io.windowVerticalLo = 0;
|
||||
io.windowVerticalHi = (data.bits(0,4) << 3) - 1;
|
||||
} else {
|
||||
//down
|
||||
io.windowVerticalLo = (data.bits(0,4) << 3) - 1;
|
||||
io.windowVerticalHi = ~0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -207,5 +332,10 @@ auto VDP::writeControlPort(uint7 addr, uint8 data) -> void {
|
|||
return;
|
||||
}
|
||||
|
||||
//unused
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
auto VDP::scanline() -> void {
|
||||
state.x = 0;
|
||||
if(++state.y >= 262) state.y = 0;
|
||||
if(state.y == 0) scheduler.exit(Scheduler::Event::Frame);
|
||||
|
||||
state.output = buffer + (state.y * 2 + 0) * 1280;
|
||||
}
|
||||
|
||||
auto VDP::run() -> void {
|
||||
if(!io.displayEnable) return outputPixel(0);
|
||||
|
||||
bool windowed = false; //todo: broken
|
||||
windowed &= state.x >= io.windowHorizontalLo && state.x <= io.windowHorizontalHi;
|
||||
windowed &= state.y >= io.windowVerticalLo && state.y <= io.windowVerticalHi;
|
||||
auto& planeA = windowed ? this->window : this->planeA;
|
||||
|
||||
planeA.run(state.x, state.y);
|
||||
planeB.run(state.x, state.y);
|
||||
|
||||
auto output = io.backgroundColor;
|
||||
if(auto color = planeB.output.color) output = color;
|
||||
if(auto color = planeA.output.color) output = color;
|
||||
if(planeB.output.priority) if(auto color = planeB.output.color) output = color;
|
||||
if(planeA.output.priority) if(auto color = planeA.output.color) output = color;
|
||||
|
||||
outputPixel(cram[output]);
|
||||
state.x++;
|
||||
}
|
||||
|
||||
auto VDP::outputPixel(uint9 color) -> void {
|
||||
for(auto n : range(4)) {
|
||||
state.output[ 0 + n] = color;
|
||||
state.output[1280 + n] = color;
|
||||
}
|
||||
state.output += 4;
|
||||
}
|
|
@ -7,32 +7,33 @@ namespace MegaDrive {
|
|||
|
||||
VDP vdp;
|
||||
#include "io.cpp"
|
||||
#include "dma.cpp"
|
||||
#include "render.cpp"
|
||||
#include "background.cpp"
|
||||
|
||||
auto VDP::Enter() -> void {
|
||||
while(true) scheduler.synchronize(), vdp.main();
|
||||
}
|
||||
|
||||
auto VDP::main() -> void {
|
||||
for(uint y : range(262)) {
|
||||
auto outputLo = buffer + (y * 2 + 0) * 1280;
|
||||
auto outputHi = buffer + (y * 2 + 1) * 1280;
|
||||
for(uint x : range(342)) {
|
||||
if(y < 240 && x < 320) {
|
||||
for(uint n : range(4)) {
|
||||
*outputLo++ = 511;
|
||||
*outputHi++ = 511;
|
||||
}
|
||||
}
|
||||
|
||||
scanline();
|
||||
if(state.y < 240) {
|
||||
for(uint x : range(320)) {
|
||||
run();
|
||||
step(1);
|
||||
}
|
||||
if(y == 240) scheduler.exit(Scheduler::Event::Frame);
|
||||
} else {
|
||||
step(342);
|
||||
}
|
||||
step(22);
|
||||
}
|
||||
|
||||
auto VDP::step(uint clocks) -> void {
|
||||
Thread::step(clocks);
|
||||
synchronize(cpu);
|
||||
while(clocks--) {
|
||||
dmaRun();
|
||||
Thread::step(1);
|
||||
synchronize(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
auto VDP::refresh() -> void {
|
||||
|
@ -40,12 +41,19 @@ auto VDP::refresh() -> void {
|
|||
}
|
||||
|
||||
auto VDP::power() -> void {
|
||||
planeA.power();
|
||||
window.power();
|
||||
planeB.power();
|
||||
}
|
||||
|
||||
auto VDP::reset() -> void {
|
||||
create(VDP::Enter, system.colorburst() * 15.0 / 10.0);
|
||||
|
||||
memory::fill(&io, sizeof(IO));
|
||||
|
||||
planeA.reset();
|
||||
window.reset();
|
||||
planeB.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,16 +9,67 @@ struct VDP : Thread {
|
|||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
//io.cpp
|
||||
auto readByte(uint24 addr) -> uint8;
|
||||
auto readWord(uint24 addr) -> uint16;
|
||||
auto writeByte(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto readWord(uint24 addr) -> uint16;
|
||||
auto writeWord(uint24 addr, uint16 data) -> void;
|
||||
|
||||
auto readDataPort() -> uint16;
|
||||
auto writeDataPort(uint16 data) -> void;
|
||||
|
||||
auto readControlPort() -> uint16;
|
||||
auto writeControlPort(uint7 addr, uint8 data) -> void;
|
||||
auto writeControlPort(uint16 data) -> void;
|
||||
|
||||
//dma.cpp
|
||||
auto dmaRun() -> void;
|
||||
auto dmaFillVRAM() -> void;
|
||||
|
||||
//render.cpp
|
||||
auto scanline() -> void;
|
||||
auto run() -> void;
|
||||
auto outputPixel(uint9 color) -> void;
|
||||
|
||||
//background.cpp
|
||||
struct Background {
|
||||
auto scanline() -> void;
|
||||
auto run(uint x, uint y) -> void;
|
||||
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
struct IO {
|
||||
uint15 nametableAddress;
|
||||
uint3 nametableWidth; //1 << value
|
||||
uint3 nametableHeight; //1 << value
|
||||
} io;
|
||||
|
||||
struct Output {
|
||||
uint6 color;
|
||||
boolean priority;
|
||||
} output;
|
||||
};
|
||||
Background planeA;
|
||||
Background window;
|
||||
Background planeB;
|
||||
|
||||
uint16 vram[32768];
|
||||
uint16 vramExpansion[32768]; //not present in stock Mega Drive hardware
|
||||
uint9 cram[64];
|
||||
uint10 vsram[40];
|
||||
|
||||
private:
|
||||
struct IO {
|
||||
//internal state
|
||||
boolean dmaActive;
|
||||
uint8 dmaFillWord;
|
||||
|
||||
//command
|
||||
uint6 command;
|
||||
uint16 address;
|
||||
boolean commandPending;
|
||||
|
||||
//$00 mode register 1
|
||||
uint1 displayOverlayEnable;
|
||||
uint1 counterLatch;
|
||||
|
@ -33,15 +84,6 @@ private:
|
|||
uint1 displayEnable;
|
||||
uint1 externalVRAM;
|
||||
|
||||
//$02 plane A name table location
|
||||
uint4 nametablePlaneA;
|
||||
|
||||
//$03 window name table location
|
||||
uint6 nametableWindow;
|
||||
|
||||
//$04 plane B name table location
|
||||
uint4 nametablePlaneB;
|
||||
|
||||
//$05 sprite attribute table location
|
||||
uint8 attrtableSprite;
|
||||
|
||||
|
@ -49,8 +91,7 @@ private:
|
|||
uint1 nametableBaseSprite;
|
||||
|
||||
//$07 background color
|
||||
uint4 backgroundIndex;
|
||||
uint2 backgroundPalette;
|
||||
uint6 backgroundColor;
|
||||
|
||||
//$0a horizontal interrupt counter
|
||||
uint8 horizontalInterruptCounter;
|
||||
|
@ -75,20 +116,16 @@ private:
|
|||
uint1 nametableBasePatternA;
|
||||
uint1 nametableBasePatternB;
|
||||
|
||||
//$0f VRAM auto-increment value
|
||||
uint8 vramAutoIncrement;
|
||||
|
||||
//$10 plane size
|
||||
uint2 horizontalPlaneSize;
|
||||
uint2 verticalPlaneSize;
|
||||
//$0f data port auto-increment value
|
||||
uint8 dataIncrement;
|
||||
|
||||
//$11 window plane horizontal position
|
||||
uint5 horizontalWindowPlanePosition;
|
||||
uint1 horizontalWindowPlaneRight;
|
||||
uint10 windowHorizontalLo;
|
||||
uint10 windowHorizontalHi;
|
||||
|
||||
//$12 window plane vertical position
|
||||
uint5 verticalWindowPlanePosition;
|
||||
uint1 verticalWindowPlaneDown;
|
||||
uint10 windowVerticalLo;
|
||||
uint10 windowVerticalHi;
|
||||
|
||||
//$13-$14 DMA length
|
||||
uint16 dmaLength;
|
||||
|
@ -98,6 +135,12 @@ private:
|
|||
uint2 dmaMode;
|
||||
} io;
|
||||
|
||||
struct State {
|
||||
uint32* output = nullptr;
|
||||
uint x;
|
||||
uint y;
|
||||
} state;
|
||||
|
||||
uint32 buffer[1280 * 480];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
auto M68K::instruction() -> void {
|
||||
instructionsExecuted++;
|
||||
|
||||
//if(instructionsExecuted >= 2000010) trap();
|
||||
//if(instructionsExecuted >= 2000000) {
|
||||
// print(disassembleRegisters(), "\n");
|
||||
// print(disassemble(r.pc), "\n");
|
||||
// print("\n");
|
||||
//}
|
||||
#if 0
|
||||
if(instructionsExecuted >= 10000010) while(true) step(1);
|
||||
if(instructionsExecuted >= 10000000) {
|
||||
print(disassembleRegisters(), "\n");
|
||||
print(disassemble(r.pc), "\n");
|
||||
print("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
opcode = readPC();
|
||||
return instructionTable[opcode]();
|
||||
|
|
|
@ -248,13 +248,10 @@ auto M68K::instructionASR(EffectiveAddress modify) -> void {
|
|||
|
||||
auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void {
|
||||
auto extension = readPC<Word>();
|
||||
if(displacement) r.pc -= 2;
|
||||
if(condition >= 2 && !testCondition(condition)) return;
|
||||
if(condition == 1) push<Long>(r.pc);
|
||||
if(condition >= 2 && !testCondition(condition)) { //0 = BRA; 1 = BSR
|
||||
if(displacement) r.pc -= 2;
|
||||
} else {
|
||||
r.pc -= 2;
|
||||
r.pc += displacement ? sign<Byte>(displacement) : sign<Word>(extension);
|
||||
}
|
||||
r.pc += displacement ? (int8_t)displacement : (int16_t)extension - 2;
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionBCHG(DataRegister bit, EffectiveAddress with) -> void {
|
||||
|
|
|
@ -35,13 +35,13 @@ struct M68K {
|
|||
};};
|
||||
|
||||
struct Vector { enum : uint {
|
||||
Illegal = 4,
|
||||
DivisionByZero = 5,
|
||||
BoundsCheck = 6,
|
||||
Overflow = 7,
|
||||
Unprivileged = 8,
|
||||
IllegalLineA = 10,
|
||||
IllegalLineF = 11,
|
||||
Illegal = 4,
|
||||
DivisionByZero = 5,
|
||||
BoundsCheck = 6,
|
||||
Overflow = 7,
|
||||
Unprivileged = 8,
|
||||
IllegalLineA = 10,
|
||||
IllegalLineF = 11,
|
||||
};};
|
||||
|
||||
M68K();
|
||||
|
|
|
@ -112,12 +112,12 @@ auto pCanvas::_paint() -> void {
|
|||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biWidth = width;
|
||||
bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside now; negative height flips bitmap
|
||||
bmi.bmiHeader.biSizeImage = pixels.size() * sizeof(uint32);
|
||||
bmi.bmiHeader.biSizeImage = pixels.size() * sizeof(uint32_t);
|
||||
void* bits = nullptr;
|
||||
HBITMAP bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, nullptr, 0);
|
||||
if(bits) {
|
||||
auto source = (const uint8*)pixels.data();
|
||||
auto target = (uint8*)bits;
|
||||
auto source = (const uint8_t*)pixels.data();
|
||||
auto target = (uint8_t*)bits;
|
||||
for(auto n : range(width * height)) {
|
||||
target[0] = (source[0] * source[3]) / 255;
|
||||
target[1] = (source[1] * source[3]) / 255;
|
||||
|
@ -155,7 +155,7 @@ auto pCanvas::_rasterize() -> void {
|
|||
pixels.resize(width * height);
|
||||
|
||||
if(auto& icon = state().icon) {
|
||||
memory::copy(pixels.data(), icon.data(), width * height * sizeof(uint32));
|
||||
memory::copy(pixels.data(), icon.data(), width * height * sizeof(uint32_t));
|
||||
} else if(auto& gradient = state().gradient) {
|
||||
auto& colors = gradient.state.colors;
|
||||
image fill;
|
||||
|
@ -163,7 +163,7 @@ auto pCanvas::_rasterize() -> void {
|
|||
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
|
||||
memory::copy(pixels.data(), fill.data(), fill.size());
|
||||
} else {
|
||||
uint32 color = state().color.value();
|
||||
uint32_t color = state().color.value();
|
||||
for(auto& pixel : pixels) pixel = color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ template<uint Bits> struct Natural {
|
|||
|
||||
struct Reference {
|
||||
inline Reference(Natural& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
|
||||
inline auto& operator=(Reference& source) { return set(source.get()); }
|
||||
|
||||
inline auto get() const -> type {
|
||||
const type RangeBits = Hi - Lo + 1;
|
||||
|
@ -162,6 +163,7 @@ template<uint Bits> struct Integer {
|
|||
|
||||
struct Reference {
|
||||
inline Reference(Integer& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
|
||||
inline auto& operator=(const Reference& source) { return set(source.get()); }
|
||||
|
||||
inline auto get() const -> utype {
|
||||
const type RangeBits = Hi - Lo + 1;
|
||||
|
|
Loading…
Reference in New Issue