Update to v094r31 release.

byuu says:

This WIP scores 448/920 tests passed.

Gave a shot at ROM prefetch that failed miserably (ranged from 409 to
494 tests passed. Nowhere near where it would be if it were implemented
correctly.)

Three remaining issues:
- ROM prefetch
- DMA timing
- timers (I suspect it's a 3-clock delay in starting, not a 3-clock into
  the future affair)

Probably only going to be able to get the timers working without heroic
amounts of effort.

MUL timing is fixed to use idle cycles.
STMIA is fixed to set sequential at the right moments.
DMA priority support is added, so DMA 0 can interrupt DMA 1 mid-transfer.

In other news ...

I'm calling gtk_widget_destroy on the GtkWindow now, so hopefully those
Window_configure issues go away.

I realize I was leaking Display* handles in the X-video driver while
I was looking at it, so I fixed those.

I added DT_NOPREFIX so the Windows ListView will show & characters
correctly now.
This commit is contained in:
Tim Allen 2015-06-25 19:52:32 +10:00
parent 310ff4fa3b
commit ea02f1e36a
17 changed files with 166 additions and 138 deletions

View File

@ -8,7 +8,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "094.30";
static const string Version = "094.31";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -10,7 +10,7 @@ namespace GameBoyAdvance {
#include "serialization.cpp"
CPU cpu;
void CPU::Enter() {
auto CPU::Enter() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
scheduler.sync = Scheduler::SynchronizeMode::All;
@ -21,7 +21,7 @@ void CPU::Enter() {
}
}
void CPU::main() {
auto CPU::main() -> void {
#if defined(DEBUG)
if(crash) {
print(cpsr().t ? disassemble_thumb_instruction(pipeline.execute.address)
@ -57,12 +57,12 @@ void CPU::main() {
exec();
}
void CPU::step(unsigned clocks) {
auto CPU::step(unsigned clocks) -> void {
timer_step(clocks);
sync_step(clocks);
}
void CPU::sync_step(unsigned clocks) {
auto CPU::sync_step(unsigned clocks) -> void {
ppu.clock -= clocks;
if(ppu.clock < 0) co_switch(ppu.thread);
@ -70,26 +70,26 @@ void CPU::sync_step(unsigned clocks) {
if(apu.clock < 0) co_switch(apu.thread);
}
void CPU::bus_idle(uint32 addr) {
auto CPU::bus_idle(uint32 addr) -> void {
step(1);
return bus.idle(addr);
}
uint32 CPU::bus_read(uint32 addr, uint32 size) {
auto CPU::bus_read(uint32 addr, uint32 size) -> uint32 {
step(bus.wait(addr, size));
return bus.read(addr, size);
}
void CPU::bus_write(uint32 addr, uint32 size, uint32 word) {
auto CPU::bus_write(uint32 addr, uint32 size, uint32 word) -> void {
step(bus.wait(addr, size));
return bus.write(addr, size, word);
}
void CPU::keypad_run() {
auto CPU::keypad_run() -> void {
if(regs.keypad.control.enable == false) return;
bool test = regs.keypad.control.condition; //0 = OR, 1 = AND
for(unsigned n = 0; n < 10; n++) {
for(auto n : range(10)) {
if(regs.keypad.control.flag[n] == false) continue;
bool input = interface->inputPoll(0, 0, n);
if(regs.keypad.control.condition == 0) test |= input;
@ -98,12 +98,12 @@ void CPU::keypad_run() {
if(test) regs.irq.flag.keypad = true;
}
void CPU::power() {
auto CPU::power() -> void {
create(CPU::Enter, 16777216);
ARM::power();
for(unsigned n = 0; n < 32 * 1024; n++) iwram[n] = 0;
for(unsigned n = 0; n < 256 * 1024; n++) ewram[n] = 0;
for(auto n : range( 32 * 1024)) iwram[n] = 0;
for(auto n : range(256 * 1024)) ewram[n] = 0;
for(auto& dma : regs.dma) {
dma.source = 0;

View File

@ -1,43 +1,50 @@
struct CPU : Processor::ARM, Thread, MMIO {
uint8* iwram;
uint8* ewram;
uint8* iwram = nullptr;
uint8* ewram = nullptr;
#include "registers.hpp"
#include "state.hpp"
static void Enter();
void main();
void step(unsigned clocks);
void sync_step(unsigned clocks);
//cpu.cpp
static auto Enter() -> void;
void bus_idle(uint32 addr);
uint32 bus_read(uint32 addr, uint32 size);
void bus_write(uint32 addr, uint32 size, uint32 word);
auto main() -> void;
auto step(unsigned clocks) -> void;
auto sync_step(unsigned clocks) -> void;
void keypad_run();
void power();
auto bus_idle(uint32 addr) -> void;
auto bus_read(uint32 addr, uint32 size) -> uint32;
auto bus_write(uint32 addr, uint32 size, uint32 word) -> void;
uint8 read(uint32 addr);
void write(uint32 addr, uint8 byte);
auto keypad_run() -> void;
auto power() -> void;
uint32 iwram_read(uint32 addr, uint32 size);
void iwram_write(uint32 addr, uint32 size, uint32 word);
uint32 ewram_read(uint32 addr, uint32 size);
void ewram_write(uint32 addr, uint32 size, uint32 word);
void dma_run();
void dma_transfer(Registers::DMA &dma);
void dma_vblank();
void dma_hblank();
void dma_hdma();
void timer_step(unsigned clocks);
void timer_increment(unsigned n);
void timer_fifo_run(unsigned n);
void serialize(serializer&);
CPU();
~CPU();
//mmio.cpp
auto read(uint32 addr) -> uint8;
auto write(uint32 addr, uint8 byte) -> void;
auto iwram_read(uint32 addr, uint32 size) -> uint32;
auto iwram_write(uint32 addr, uint32 size, uint32 word) -> void;
auto ewram_read(uint32 addr, uint32 size) -> uint32;
auto ewram_write(uint32 addr, uint32 size, uint32 word) -> void;
//dma.cpp
auto dma_run() -> void;
auto dma_exec(Registers::DMA& dma) -> void;
auto dma_vblank() -> void;
auto dma_hblank() -> void;
auto dma_hdma() -> void;
//timer.cpp
auto timer_step(unsigned clocks) -> void;
auto timer_increment(unsigned n) -> void;
auto timer_fifo_run(unsigned n) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
};
extern CPU cpu;

View File

@ -1,29 +1,38 @@
void CPU::dma_run() {
for(unsigned n = 0; n < 4; n++) {
auto CPU::dma_run() -> void {
while(true) {
bool transferred = false;
for(auto n : range(4)) {
auto& dma = regs.dma[n];
if(dma.pending) {
dma.pending = false;
dma_transfer(dma);
dma_exec(dma);
if(dma.control.irq) regs.irq.flag.dma[n] = 1;
if(dma.control.drq && n == 3) regs.irq.flag.cartridge = 1;
transferred = true;
break;
}
}
if(!transferred) break;
}
}
void CPU::dma_transfer(Registers::DMA& dma) {
auto CPU::dma_exec(Registers::DMA& dma) -> void {
unsigned size = dma.control.size ? Word : Half;
unsigned seek = dma.control.size ? 4 : 2;
if(dma.run.length == dma.length) {
idle();
idle();
sequential() = false;
do {
} else {
sequential() = true;
}
step(bus.wait(dma.run.source, size));
uint32 word = bus.read(dma.run.source, size);
step(bus.wait(dma.run.target, size));
bus.write(dma.run.target, size, word);
sequential() = true;
switch(dma.control.sourcemode) {
case 0: dma.run.source += seek; break;
case 1: dma.run.source -= seek; break;
@ -34,27 +43,28 @@ void CPU::dma_transfer(Registers::DMA& dma) {
case 1: dma.run.target -= seek; break;
case 3: dma.run.target += seek; break;
}
} while(--dma.run.length);
sequential() = false;
if(--dma.run.length == 0) {
dma.pending = false;
if(dma.control.targetmode == 3) dma.run.target = dma.target;
if(dma.control.repeat == 1) dma.run.length = dma.length;
if(dma.control.repeat == 0) dma.control.enable = false;
}
}
void CPU::dma_vblank() {
auto CPU::dma_vblank() -> void {
for(auto& dma : regs.dma) {
if(dma.control.enable && dma.control.timingmode == 1) dma.pending = true;
}
}
void CPU::dma_hblank() {
auto CPU::dma_hblank() -> void {
for(auto& dma : regs.dma) {
if(dma.control.enable && dma.control.timingmode == 2) dma.pending = true;
}
}
void CPU::dma_hdma() {
auto CPU::dma_hdma() -> void {
auto& dma = regs.dma[3];
if(dma.control.enable && dma.control.timingmode == 3) dma.pending = true;
}

View File

@ -1,4 +1,4 @@
uint32 CPU::iwram_read(uint32 addr, uint32 size) {
auto CPU::iwram_read(uint32 addr, uint32 size) -> uint32 {
if(regs.memory.control.disable) return cpu.pipeline.fetch.instruction;
if(size == Word) return iwram_read(addr &~ 2, Half) << 0 | iwram_read(addr | 2, Half) << 16;
@ -7,7 +7,7 @@ uint32 CPU::iwram_read(uint32 addr, uint32 size) {
return iwram[addr & 0x7fff];
}
void CPU::iwram_write(uint32 addr, uint32 size, uint32 word) {
auto CPU::iwram_write(uint32 addr, uint32 size, uint32 word) -> void {
if(regs.memory.control.disable) return;
if(size == Word) {
@ -25,7 +25,7 @@ void CPU::iwram_write(uint32 addr, uint32 size, uint32 word) {
iwram[addr & 0x7fff] = word;
}
uint32 CPU::ewram_read(uint32 addr, uint32 size) {
auto CPU::ewram_read(uint32 addr, uint32 size) -> uint32 {
if(regs.memory.control.disable) return cpu.pipeline.fetch.instruction;
if(regs.memory.control.ewram == false) return iwram_read(addr, size);
@ -35,7 +35,7 @@ uint32 CPU::ewram_read(uint32 addr, uint32 size) {
return ewram[addr & 0x3ffff];
}
void CPU::ewram_write(uint32 addr, uint32 size, uint32 word) {
auto CPU::ewram_write(uint32 addr, uint32 size, uint32 word) -> void {
if(regs.memory.control.disable) return;
if(regs.memory.control.ewram == false) return iwram_write(addr, size, word);

View File

@ -1,4 +1,4 @@
uint8 CPU::read(uint32 addr) {
auto CPU::read(uint32 addr) -> uint8 {
uint8 result = 0;
switch(addr) {
@ -137,7 +137,7 @@ uint8 CPU::read(uint32 addr) {
return 0u;
}
void CPU::write(uint32 addr, uint8 byte) {
auto CPU::write(uint32 addr, uint8 byte) -> void {
switch(addr) {
//DMA0SAD

View File

@ -11,7 +11,7 @@ CPU::Registers::DMAControl::operator uint16() const {
);
}
uint16 CPU::Registers::DMAControl::operator=(uint16 source) {
auto CPU::Registers::DMAControl::operator=(uint16 source) -> uint16 {
targetmode = source >> 5;
sourcemode = source >> 7;
repeat = source >> 9;
@ -32,7 +32,7 @@ CPU::Registers::TimerControl::operator uint16() const {
);
}
uint16 CPU::Registers::TimerControl::operator=(uint16 source) {
auto CPU::Registers::TimerControl::operator=(uint16 source) -> uint16 {
frequency = source >> 0;
cascade = source >> 2;
irq = source >> 6;
@ -52,7 +52,7 @@ CPU::Registers::SerialControl::operator uint16() const {
);
}
uint16 CPU::Registers::SerialControl::operator=(uint16 source) {
auto CPU::Registers::SerialControl::operator=(uint16 source) -> uint16 {
shiftclockselect = source >> 0;
shiftclockfrequency = source >> 1;
transferenablereceive = source >> 2;
@ -80,7 +80,7 @@ CPU::Registers::KeypadControl::operator uint16() const {
);
}
uint16 CPU::Registers::KeypadControl::operator=(uint16 source) {
auto CPU::Registers::KeypadControl::operator=(uint16 source) -> uint16 {
flag[0] = source >> 0;
flag[1] = source >> 1;
flag[2] = source >> 2;
@ -111,7 +111,7 @@ CPU::Registers::JoybusSettings::operator uint16() const {
);
}
uint16 CPU::Registers::JoybusSettings::operator=(uint16 source) {
auto CPU::Registers::JoybusSettings::operator=(uint16 source) -> uint16 {
sc = source >> 0;
sd = source >> 1;
si = source >> 2;
@ -134,7 +134,7 @@ CPU::Registers::JoybusControl::operator uint16() const {
);
}
uint16 CPU::Registers::JoybusControl::operator=(uint16 source) {
auto CPU::Registers::JoybusControl::operator=(uint16 source) -> uint16 {
resetsignal = source >> 0;
receivecomplete = source >> 1;
sendcomplete = source >> 2;
@ -150,7 +150,7 @@ CPU::Registers::JoybusStatus::operator uint16() const {
);
}
uint16 CPU::Registers::JoybusStatus::operator=(uint16 source) {
auto CPU::Registers::JoybusStatus::operator=(uint16 source) -> uint16 {
receiveflag = source >> 1;
sendflag = source >> 3;
generalflag = source >> 4;
@ -176,7 +176,7 @@ CPU::Registers::Interrupt::operator uint16() const {
);
}
uint16 CPU::Registers::Interrupt::operator=(uint16 source) {
auto CPU::Registers::Interrupt::operator=(uint16 source) -> uint16 {
vblank = source >> 0;
hblank = source >> 1;
vcoincidence = source >> 2;
@ -209,7 +209,7 @@ CPU::Registers::WaitControl::operator uint16() const {
);
}
uint16 CPU::Registers::WaitControl::operator=(uint16 source) {
auto CPU::Registers::WaitControl::operator=(uint16 source) -> uint16 {
nwait[3] = (source >> 0) & 3;
nwait[0] = (source >> 2) & 3;
swait[0] = (source >> 4) & 1;
@ -234,7 +234,7 @@ CPU::Registers::MemoryControl::operator uint32() const {
);
}
uint32 CPU::Registers::MemoryControl::operator=(uint32 source) {
auto CPU::Registers::MemoryControl::operator=(uint32 source) -> uint32 {
disable = source >> 0;
unknown1 = source >> 1;
ewram = source >> 5;

View File

@ -10,8 +10,8 @@ struct Registers {
uint1 enable;
operator uint16() const;
uint16 operator=(uint16 source);
DMAControl& operator=(const DMAControl&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const DMAControl&) -> DMAControl& = delete;
};
struct DMA {
@ -36,8 +36,8 @@ struct Registers {
uint1 enable;
operator uint16() const;
uint16 operator=(uint16 source);
TimerControl& operator=(const TimerControl&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const TimerControl&) -> TimerControl& = delete;
};
struct Timer {
@ -56,8 +56,8 @@ struct Registers {
uint1 irqenable;
operator uint16() const;
uint16 operator=(uint16 source);
SerialControl& operator=(const SerialControl&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const SerialControl&) -> SerialControl& = delete;
};
struct Serial {
@ -72,8 +72,8 @@ struct Registers {
uint1 condition;
operator uint16() const;
uint16 operator=(uint16 source);
KeypadControl& operator=(const KeypadControl&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const KeypadControl&) -> KeypadControl& = delete;
};
struct Keypad {
@ -93,8 +93,8 @@ struct Registers {
uint2 mode;
operator uint16() const;
uint16 operator=(uint16 source);
JoybusSettings& operator=(const JoybusSettings&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const JoybusSettings&) -> JoybusSettings& = delete;
};
struct JoybusControl {
@ -104,8 +104,8 @@ struct Registers {
uint1 irqenable;
operator uint16() const;
uint16 operator=(uint16 source);
JoybusControl& operator=(const JoybusControl&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const JoybusControl&) -> JoybusControl& = delete;
};
struct JoybusStatus {
@ -114,8 +114,8 @@ struct Registers {
uint2 generalflag;
operator uint16() const;
uint16 operator=(uint16 source);
JoybusStatus& operator=(const JoybusStatus&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const JoybusStatus&) -> JoybusStatus& = delete;
};
struct Joybus {
@ -139,8 +139,8 @@ struct Registers {
uint1 cartridge;
operator uint16() const;
uint16 operator=(uint16 source);
Interrupt& operator=(const Interrupt&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const Interrupt&) -> Interrupt& = delete;
};
struct IRQ {
@ -156,8 +156,8 @@ struct Registers {
uint1 gametype;
operator uint16() const;
uint16 operator=(uint16 source);
WaitControl& operator=(const WaitControl&) = delete;
auto operator=(uint16 source) -> uint16;
auto operator=(const WaitControl&) -> WaitControl& = delete;
};
struct Wait {
@ -172,8 +172,8 @@ struct Registers {
uint4 unknown2;
operator uint32() const;
uint32 operator=(uint32 source);
MemoryControl& operator=(const MemoryControl&) = delete;
auto operator=(uint32 source) -> uint32;
auto operator=(const MemoryControl&) -> MemoryControl& = delete;
};
struct Memory {

View File

@ -1,4 +1,4 @@
void CPU::serialize(serializer& s) {
auto CPU::serialize(serializer& s) -> void {
ARM::serialize(s);
Thread::serialize(s);

View File

@ -1,4 +1,4 @@
void CPU::timer_step(unsigned clocks) {
auto CPU::timer_step(unsigned clocks) -> void {
for(unsigned c = 0; c < clocks; c++) {
for(unsigned n = 0; n < 4; n++) {
auto& timer = regs.timer[n];
@ -14,7 +14,7 @@ void CPU::timer_step(unsigned clocks) {
}
}
void CPU::timer_increment(unsigned n) {
auto CPU::timer_increment(unsigned n) -> void {
auto& timer = regs.timer[n];
if(++timer.period == 0) {
timer.period = timer.reload;
@ -30,7 +30,7 @@ void CPU::timer_increment(unsigned n) {
}
}
void CPU::timer_fifo_run(unsigned n) {
auto CPU::timer_fifo_run(unsigned n) -> void {
apu.fifo[n].read();
if(apu.fifo[n].size > 16) return;

View File

@ -30,12 +30,12 @@ else
endif
ifeq ($(hiro),gtk)
hiroflags = $(cppflags) $(flags) -DHIRO_GTK `pkg-config --cflags gtk+-2.0 gtksourceview-2.0`
hirolink = `pkg-config --libs gtk+-2.0 gtksourceview-2.0` -lX11
hiroflags = $(cppflags) $(flags) -DHIRO_GTK $(shell pkg-config --cflags gtk+-2.0 gtksourceview-2.0)
hirolink = -lX11 $(shell pkg-config --libs gtk+-2.0 gtksourceview-2.0)
endif
ifeq ($(hiro),qt)
hiroflags = $(cppflags) $(flags) -DHIRO_QT `pkg-config --cflags QtCore QtGui`
hirolink = `pkg-config --libs QtCore QtGui` -lX11
hiroflags = $(cppflags) $(flags) -DHIRO_QT $(shell pkg-config --cflags QtCore QtGui)
hirolink = -lX11 $(shell pkg-config --libs QtCore QtGui)
endif
endif

View File

@ -182,6 +182,7 @@ auto pWindow::construct() -> void {
}
auto pWindow::destruct() -> void {
gtk_widget_destroy(widget);
}
auto pWindow::append(sLayout layout) -> void {

View File

@ -307,7 +307,7 @@ auto pListView::onCustomDraw(LPARAM lparam) -> LRESULT {
utf16_t wText(text);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, selected ? GetSysColor(COLOR_HIGHLIGHTTEXT) : CreateRGB(_foregroundColor(row, column)));
auto style = DT_SINGLELINE | DT_END_ELLIPSIS;
auto style = DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS;
style |= halign < 0.333 ? DT_LEFT : halign > 0.666 ? DT_RIGHT : DT_CENTER;
style |= valign < 0.333 ? DT_TOP : valign > 0.666 ? DT_BOTTOM : DT_VCENTER;
rc.right -= 2;

View File

@ -45,10 +45,10 @@ auto ARM::sub(uint32 source, uint32 modify, bool carry) -> uint32 {
}
auto ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) -> uint32 {
if((multiplier & 0xffffff00) == 0x00000000 || (multiplier & 0xffffff00 == 0xffffff00)) step(1);
else if((multiplier & 0xffff0000) == 0x00000000 || (multiplier & 0xffff0000 == 0xffff0000)) step(2);
else if((multiplier & 0xff000000) == 0x00000000 || (multiplier & 0xff000000 == 0xff000000)) step(3);
else step(4);
idle();
if((multiplier & 0xffffff00) != 0x00000000 && (multiplier & 0xffffff00) != 0xffffff00) idle();
if((multiplier & 0xffff0000) != 0x00000000 && (multiplier & 0xffff0000) != 0xffff0000) idle();
if((multiplier & 0xff000000) != 0x00000000 && (multiplier & 0xff000000) != 0xff000000) idle();
product += multiplicand * multiplier;

View File

@ -521,9 +521,9 @@ auto ARM::arm_op_move_multiple() {
if(usr) processor.setMode(Processor::Mode::USR);
sequential() = false;
for(unsigned m = 0; m < 16; m++) {
if(list & (1 << m)) {
sequential() = false;
if(list & 1 << m) {
if(l == 1) r(m) = read(rn, Word);
if(l == 0) write(rn, Word, r(m));
rn += 4;

View File

@ -5,7 +5,7 @@ else
endif
rubyflags += $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
rubyflags += $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
rubyflags += $(if $(findstring .sdl,$(ruby)),$(shell sdl-config --cflags))
rubylink =
@ -26,7 +26,7 @@ rubylink += $(if $(findstring audio.xaudio2,$(ruby)),-lole32)
rubylink += $(if $(findstring input.udev,$(ruby)),-ludev)
rubylink += $(if $(findstring input.windows,$(ruby)),-ldinput8 -ldxguid)
rubylink += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
rubylink += $(if $(findstring .sdl,$(ruby)),$(shell sdl-config --libs))
ifeq ($(platform),windows)
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)

View File

@ -54,7 +54,10 @@ struct VideoXv : Video {
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) {
return XInternAtom(XOpenDisplay(0), "XV_SYNC_TO_VBLANK", true) != None;
Display* display = XOpenDisplay(nullptr);
bool result = XInternAtom(display, "XV_SYNC_TO_VBLANK", true) != None;
XCloseDisplay(display);
return result;
}
return false;
}
@ -72,14 +75,16 @@ struct VideoXv : Video {
}
if(name == Video::Synchronize && value.is<bool>()) {
Display* display = XOpenDisplay(0);
bool result = false;
Display* display = XOpenDisplay(nullptr);
Atom atom = XInternAtom(display, "XV_SYNC_TO_VBLANK", true);
if(atom != None && device.port >= 0) {
settings.synchronize = value.get<bool>();
XvSetPortAttribute(display, device.port, atom, settings.synchronize);
return true;
result = true;
}
return false;
XCloseDisplay(display);
return result;
}
return false;
@ -92,7 +97,7 @@ struct VideoXv : Video {
XShmDetach(device.display, &device.shminfo);
shmdt(device.shminfo.shmaddr);
shmctl(device.shminfo.shmid, IPC_RMID, NULL);
shmctl(device.shminfo.shmid, IPC_RMID, nullptr);
XFree(device.image);
delete[] buffer;
@ -161,7 +166,7 @@ struct VideoXv : Video {
}
auto init() -> bool {
device.display = XOpenDisplay(0);
device.display = XOpenDisplay(nullptr);
if(!XShmQueryExtension(device.display)) {
fprintf(stderr, "VideoXv: XShm extension not found.\n");
@ -202,7 +207,7 @@ struct VideoXv : Video {
visualtemplate.depth = device.depth;
visualtemplate.visual = 0;
signed visualmatches = 0;
XVisualInfo *visualinfo = XGetVisualInfo(device.display, VisualIDMask | VisualScreenMask | VisualDepthMask, &visualtemplate, &visualmatches);
XVisualInfo* visualinfo = XGetVisualInfo(device.display, VisualIDMask | VisualScreenMask | VisualDepthMask, &visualtemplate, &visualmatches);
if(visualmatches < 1 || !visualinfo->visual) {
if(visualinfo) XFree(visualinfo);
fprintf(stderr, "VideoXv: unable to find Xv-compatible visual.\n");
@ -323,7 +328,7 @@ struct VideoXv : Video {
auto term() -> void {
XShmDetach(device.display, &device.shminfo);
shmdt(device.shminfo.shmaddr);
shmctl(device.shminfo.shmid, IPC_RMID, NULL);
shmctl(device.shminfo.shmid, IPC_RMID, nullptr);
XFree(device.image);
if(device.window) {
@ -336,6 +341,11 @@ struct VideoXv : Video {
device.colormap = 0;
}
if(device.display) {
XCloseDisplay(device.display);
device.display = nullptr;
}
if(buffer) { delete[] buffer; buffer = nullptr; }
if(ytable) { delete[] ytable; ytable = nullptr; }
if(utable) { delete[] utable; utable = nullptr; }