mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-05-24 23:24:54 +00:00
+125
-113
@@ -125,119 +125,131 @@ set(CMAKE_AUTOUIC ON)
|
||||
|
||||
# make app
|
||||
add_executable(ComSquare
|
||||
sources/main.cpp
|
||||
sources/SNES.cpp
|
||||
sources/SNES.hpp
|
||||
sources/Memory/MemoryBus.cpp
|
||||
sources/Memory/MemoryBus.hpp
|
||||
sources/Memory/AMemory.hpp
|
||||
sources/Memory/AMemory.cpp
|
||||
sources/PPU/PPU.cpp
|
||||
sources/PPU/PPU.hpp
|
||||
sources/CPU/CPU.cpp
|
||||
sources/CPU/CPU.hpp
|
||||
sources/Cartridge/Cartridge.cpp
|
||||
sources/Cartridge/Cartridge.hpp
|
||||
sources/Exceptions/NotImplementedException.hpp
|
||||
sources/APU/APU.hpp
|
||||
sources/APU/APU.cpp
|
||||
sources/Exceptions/InvalidAddress.hpp
|
||||
sources/Exceptions/InvalidRom.hpp
|
||||
sources/Models/Int24.hpp
|
||||
sources/Models/Int24.hpp
|
||||
sources/Ram/Ram.cpp
|
||||
sources/Ram/Ram.hpp
|
||||
sources/Memory/MemoryShadow.cpp
|
||||
sources/Memory/MemoryShadow.hpp
|
||||
sources/Memory/ARectangleMemory.cpp
|
||||
sources/Memory/ARectangleMemory.hpp
|
||||
sources/APU/DSP/DSP.cpp
|
||||
sources/APU/DSP/DSP.hpp
|
||||
sources/Renderer/IRenderer.hpp
|
||||
sources/Renderer/SFRenderer.hpp
|
||||
sources/Renderer/SFRenderer.cpp
|
||||
sources/Exceptions/InvalidAction.hpp
|
||||
sources/Cartridge/InterruptVectors.hpp
|
||||
sources/Memory/RectangleShadow.cpp
|
||||
sources/Memory/RectangleShadow.hpp
|
||||
sources/Exceptions/InvalidOpcode.hpp
|
||||
sources/CPU/Instructions/Interrupts.cpp
|
||||
sources/CPU/Instructions/MathematicalOperations.cpp
|
||||
sources/APU/Instructions/Standbys.cpp
|
||||
sources/APU/Instructions/ProgramStatusWord.cpp
|
||||
sources/APU/Instructions/Bit.cpp
|
||||
sources/CPU/Instructions/MathematicalOperations.cpp
|
||||
sources/CPU/Instructions/MemoryInstructions.cpp
|
||||
sources/CPU/Instructions/InternalInstruction.cpp
|
||||
sources/Ram/ExtendedRam.cpp
|
||||
sources/Ram/ExtendedRam.hpp
|
||||
sources/Debugger/CPU/CPUDebug.cpp
|
||||
sources/Debugger/CPU/CPUDebug.hpp
|
||||
sources/Renderer/QtRenderer/QtSFML.cpp
|
||||
sources/Renderer/QtRenderer/QtSFML.hpp
|
||||
sources/Renderer/QtRenderer/QtWidgetSFML.cpp
|
||||
sources/Renderer/QtRenderer/QtWidgetSFML.hpp
|
||||
ui/cpuView.ui
|
||||
ui/ramView.ui
|
||||
ui/cartridgeView.ui
|
||||
ui/apuView.ui
|
||||
ui/busView.ui
|
||||
resources/appResources.qrc
|
||||
sources/Utility/Utility.hpp
|
||||
sources/Debugger/MemoryViewer.cpp
|
||||
sources/Debugger/MemoryViewer.hpp
|
||||
sources/Utility/Utility.cpp
|
||||
sources/Debugger/HeaderViewer.cpp
|
||||
sources/Debugger/HeaderViewer.hpp
|
||||
sources/CPU/Instructions/BitsInstructions.cpp
|
||||
sources/Debugger/HeaderViewer.cpp
|
||||
sources/Debugger/HeaderViewer.hpp
|
||||
sources/Debugger/APUDebug.hpp
|
||||
sources/Debugger/APUDebug.cpp
|
||||
sources/APU/Instructions/Stack.cpp
|
||||
sources/APU/Instructions/Subroutine.cpp
|
||||
sources/APU/Instructions/ProgramFlow.cpp
|
||||
sources/APU/Operand.cpp
|
||||
sources/APU/Instructions/DecimalCompensation.cpp
|
||||
sources/APU/Instructions/MultiplicationDivision.cpp
|
||||
sources/APU/Instructions/16bitArithmetic.cpp
|
||||
sources/APU/Instructions/16bitDataTransmission.cpp
|
||||
sources/APU/Instructions/8bitShiftRotation.cpp
|
||||
sources/APU/Instructions/8bitIncrementDecrement.cpp
|
||||
sources/APU/Instructions/8bitLogical.cpp
|
||||
sources/APU/Instructions/8bitArithmetic.cpp
|
||||
sources/APU/Instructions/8bitDataTransmission.cpp
|
||||
sources/APU/IPL/IPL.hpp
|
||||
sources/APU/IPL/IPL.cpp
|
||||
sources/CPU/Instructions/TransferRegisters.cpp
|
||||
sources/CPU/AddressingModes.cpp
|
||||
sources/Debugger/MemoryBusDebug.cpp
|
||||
sources/Debugger/MemoryBusDebug.hpp
|
||||
sources/Debugger/ClosableWindow.hpp
|
||||
sources/Models/Components.hpp
|
||||
sources/CPU/Instruction.hpp
|
||||
sources/Exceptions/DebuggableError.hpp
|
||||
sources/Debugger/CPU/Disassembly.cpp
|
||||
sources/Models/Components.hpp
|
||||
sources/Debugger/CGramDebug.cpp
|
||||
sources/Debugger/CGramDebug.hpp
|
||||
sources/Models/Vector2.hpp
|
||||
sources/PPU/Background.cpp
|
||||
sources/PPU/Background.hpp
|
||||
sources/CPU/DMA/DMA.cpp
|
||||
sources/CPU/DMA/DMA.hpp
|
||||
ui/registersView.ui
|
||||
sources/Debugger/RegisterViewer.cpp
|
||||
sources/Debugger/RegisterViewer.hpp
|
||||
sources/Memory/IMemory.hpp
|
||||
sources/APU/DSP/Voice.cpp
|
||||
sources/APU/DSP/Echo.cpp
|
||||
sources/APU/DSP/Gauss.cpp
|
||||
sources/APU/DSP/Envelope.cpp
|
||||
sources/APU/DSP/Timer.cpp
|
||||
sources/APU/DSP/BRR.cpp
|
||||
sources/PPU/PPUUtils.cpp
|
||||
)
|
||||
sources/main.cpp
|
||||
sources/SNES.cpp
|
||||
sources/SNES.hpp
|
||||
sources/Memory/MemoryBus.cpp
|
||||
sources/Memory/MemoryBus.hpp
|
||||
sources/Memory/AMemory.hpp
|
||||
sources/Memory/AMemory.cpp
|
||||
sources/PPU/PPU.cpp
|
||||
sources/PPU/PPU.hpp
|
||||
sources/CPU/CPU.cpp
|
||||
sources/CPU/CPU.hpp
|
||||
sources/Cartridge/Cartridge.cpp
|
||||
sources/Cartridge/Cartridge.hpp
|
||||
sources/Exceptions/NotImplementedException.hpp
|
||||
sources/APU/APU.hpp
|
||||
sources/APU/APU.cpp
|
||||
sources/Exceptions/InvalidAddress.hpp
|
||||
sources/Exceptions/InvalidRom.hpp
|
||||
sources/Models/Int24.hpp
|
||||
sources/Models/Int24.hpp
|
||||
sources/Ram/Ram.cpp
|
||||
sources/Ram/Ram.hpp
|
||||
sources/Memory/MemoryShadow.cpp
|
||||
sources/Memory/MemoryShadow.hpp
|
||||
sources/Memory/ARectangleMemory.cpp
|
||||
sources/Memory/ARectangleMemory.hpp
|
||||
sources/APU/DSP/DSP.cpp
|
||||
sources/APU/DSP/DSP.hpp
|
||||
sources/Renderer/IRenderer.hpp
|
||||
sources/Renderer/SFRenderer.hpp
|
||||
sources/Renderer/SFRenderer.cpp
|
||||
sources/Exceptions/InvalidAction.hpp
|
||||
sources/Cartridge/InterruptVectors.hpp
|
||||
sources/Memory/RectangleShadow.cpp
|
||||
sources/Memory/RectangleShadow.hpp
|
||||
sources/Exceptions/InvalidOpcode.hpp
|
||||
sources/CPU/Instructions/Interrupts.cpp
|
||||
sources/CPU/Instructions/MathematicalOperations.cpp
|
||||
sources/APU/Instructions/Standbys.cpp
|
||||
sources/APU/Instructions/ProgramStatusWord.cpp
|
||||
sources/APU/Instructions/Bit.cpp
|
||||
sources/CPU/Instructions/MathematicalOperations.cpp
|
||||
sources/CPU/Instructions/MemoryInstructions.cpp
|
||||
sources/CPU/Instructions/InternalInstruction.cpp
|
||||
sources/Ram/ExtendedRam.cpp
|
||||
sources/Ram/ExtendedRam.hpp
|
||||
sources/Debugger/CPU/CPUDebug.cpp
|
||||
sources/Debugger/CPU/CPUDebug.hpp
|
||||
sources/Renderer/QtRenderer/QtSFML.cpp
|
||||
sources/Renderer/QtRenderer/QtSFML.hpp
|
||||
sources/Renderer/QtRenderer/QtWidgetSFML.cpp
|
||||
sources/Renderer/QtRenderer/QtWidgetSFML.hpp
|
||||
ui/cpuView.ui
|
||||
ui/ramView.ui
|
||||
ui/cartridgeView.ui
|
||||
ui/apuView.ui
|
||||
ui/busView.ui
|
||||
resources/appResources.qrc
|
||||
sources/Utility/Utility.hpp
|
||||
sources/Debugger/MemoryViewer.cpp
|
||||
sources/Debugger/MemoryViewer.hpp
|
||||
sources/Utility/Utility.cpp
|
||||
sources/Debugger/HeaderViewer.cpp
|
||||
sources/Debugger/HeaderViewer.hpp
|
||||
sources/CPU/Instructions/BitsInstructions.cpp
|
||||
sources/Debugger/HeaderViewer.cpp
|
||||
sources/Debugger/HeaderViewer.hpp
|
||||
sources/Debugger/APUDebug.hpp
|
||||
sources/Debugger/APUDebug.cpp
|
||||
sources/APU/Instructions/Stack.cpp
|
||||
sources/APU/Instructions/Subroutine.cpp
|
||||
sources/APU/Instructions/ProgramFlow.cpp
|
||||
sources/APU/Operand.cpp
|
||||
sources/APU/Instructions/DecimalCompensation.cpp
|
||||
sources/APU/Instructions/MultiplicationDivision.cpp
|
||||
sources/APU/Instructions/16bitArithmetic.cpp
|
||||
sources/APU/Instructions/16bitDataTransmission.cpp
|
||||
sources/APU/Instructions/8bitShiftRotation.cpp
|
||||
sources/APU/Instructions/8bitIncrementDecrement.cpp
|
||||
sources/APU/Instructions/8bitLogical.cpp
|
||||
sources/APU/Instructions/8bitArithmetic.cpp
|
||||
sources/APU/Instructions/8bitDataTransmission.cpp
|
||||
sources/APU/IPL/IPL.hpp
|
||||
sources/APU/IPL/IPL.cpp
|
||||
sources/CPU/Instructions/TransferRegisters.cpp
|
||||
sources/CPU/AddressingModes.cpp
|
||||
sources/Debugger/MemoryBusDebug.cpp
|
||||
sources/Debugger/MemoryBusDebug.hpp
|
||||
sources/Debugger/ClosableWindow.hpp
|
||||
sources/Models/Components.hpp
|
||||
sources/CPU/Instruction.hpp
|
||||
sources/Exceptions/DebuggableError.hpp
|
||||
sources/Debugger/CPU/Disassembly.cpp
|
||||
sources/Models/Components.hpp
|
||||
sources/Debugger/CGramDebug.cpp
|
||||
sources/Debugger/CGramDebug.hpp
|
||||
sources/Models/Vector2.hpp
|
||||
sources/PPU/Background.cpp
|
||||
sources/PPU/Background.hpp
|
||||
sources/CPU/DMA/DMA.cpp
|
||||
sources/CPU/DMA/DMA.hpp
|
||||
ui/registersView.ui
|
||||
sources/Debugger/RegisterViewer.cpp
|
||||
sources/Debugger/RegisterViewer.hpp
|
||||
sources/Memory/IMemory.hpp
|
||||
sources/APU/DSP/Voice.cpp
|
||||
sources/APU/DSP/Echo.cpp
|
||||
sources/APU/DSP/Gauss.cpp
|
||||
sources/APU/DSP/Envelope.cpp
|
||||
sources/APU/DSP/Timer.cpp
|
||||
sources/APU/DSP/BRR.cpp
|
||||
sources/PPU/PPUUtils.cpp
|
||||
ui/tileView.ui
|
||||
sources/Debugger/TileViewer/TileViewer.cpp
|
||||
sources/Debugger/TileViewer/TileViewer.hpp
|
||||
sources/Debugger/TileViewer/RAMTileRenderer.cpp
|
||||
sources/Debugger/TileViewer/RAMTileRenderer.hpp
|
||||
sources/PPU/Tile.hpp
|
||||
sources/Renderer/QtRenderer/QtSfmlTileRenderer.cpp
|
||||
sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp
|
||||
sources/PPU/TileRenderer.cpp
|
||||
sources/PPU/TileRenderer.hpp
|
||||
)
|
||||
|
||||
include_directories(ComSquare sources)
|
||||
|
||||
target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED)
|
||||
include_directories(ComSquare sources)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <QtWidgets/QStyledItemDelegate>
|
||||
#include "../../CPU/CPU.hpp"
|
||||
#include "../../Renderer/SFRenderer.hpp"
|
||||
#include "../../SNES.hpp"
|
||||
#include "../../../ui/ui_cpuView.h"
|
||||
#include "../ClosableWindow.hpp"
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// Created by cbihan on 24/05/2021.
|
||||
//
|
||||
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include "RAMTileRenderer.hpp"
|
||||
#include "PPU/PPU.hpp"
|
||||
#include "PPU/Tile.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace ComSquare::Debugger
|
||||
{
|
||||
RAMTileRenderer::RAMTileRenderer()
|
||||
: _ram(nullptr),
|
||||
_renderSize(0x5000),
|
||||
_nbColumns(16),
|
||||
_ramOffset(0),
|
||||
_bpp(2),
|
||||
buffer({{{0}}})
|
||||
{
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setRam(std::shared_ptr<Ram::Ram> ram)
|
||||
{
|
||||
this->_ram = ram;
|
||||
this->_tileRenderer.setRam(ram);
|
||||
}
|
||||
|
||||
void RAMTileRenderer::render()
|
||||
{
|
||||
int bufX = 0;
|
||||
int bufY = 0;
|
||||
int nbTilesDrawn = 0;
|
||||
int resetX = bufX;
|
||||
for (auto &i : buffer)
|
||||
i.fill(0);
|
||||
uint24_t limit = fmin(this->_ram->getSize(), this->_renderSize) + this->_ramOffset;
|
||||
|
||||
for (uint24_t i = this->_ramOffset; i < limit; i += PPU::Tile::BaseByteSize * this->_bpp, nbTilesDrawn++) {
|
||||
if (bufX > 1024 || bufY > 1024)
|
||||
break;
|
||||
|
||||
this->_tileRenderer.render(i);
|
||||
if (nbTilesDrawn) {
|
||||
resetX += PPU::Tile::NbPixelsWidth;
|
||||
bufX = resetX;
|
||||
bufY -= PPU::Tile::NbPixelsHeight;
|
||||
}
|
||||
if (nbTilesDrawn && nbTilesDrawn % this->_nbColumns == 0) {
|
||||
nbTilesDrawn = 0;
|
||||
resetX = 0;
|
||||
bufX = resetX;
|
||||
bufY += PPU::Tile::NbPixelsHeight;
|
||||
}
|
||||
|
||||
for (const auto &raw : this->_tileRenderer.buffer) {
|
||||
for (const auto &pixel : raw) {
|
||||
buffer[bufX++][bufY] = pixel;
|
||||
}
|
||||
bufY++;
|
||||
bufX = resetX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setPaletteIndex(int paletteIndex)
|
||||
{
|
||||
this->_tileRenderer.setPaletteIndex(paletteIndex);
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setBpp(int bpp)
|
||||
{
|
||||
this->_bpp = bpp;
|
||||
this->_tileRenderer.setBpp(bpp);
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setCgram(std::shared_ptr<Ram::Ram> ram)
|
||||
{
|
||||
this->_tileRenderer.setCgram(ram);
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setRenderSize(int size)
|
||||
{
|
||||
this->_renderSize = size;
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setNbColumns(int nbColumns)
|
||||
{
|
||||
this->_nbColumns = nbColumns;
|
||||
}
|
||||
|
||||
int RAMTileRenderer::getBpp() const
|
||||
{
|
||||
return this->_tileRenderer.getBpp();
|
||||
}
|
||||
|
||||
int RAMTileRenderer::getPaletteIndex() const
|
||||
{
|
||||
return this->_tileRenderer.getPaletteIndex();
|
||||
}
|
||||
|
||||
int RAMTileRenderer::getNbColumns() const
|
||||
{
|
||||
return this->_nbColumns;
|
||||
}
|
||||
|
||||
void RAMTileRenderer::setRamOffset(int offset)
|
||||
{
|
||||
this->_ramOffset = offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Created by cbihan on 24/05/2021.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "PPU/TileRenderer.hpp"
|
||||
#include "Ram/Ram.hpp"
|
||||
|
||||
namespace ComSquare::Debugger
|
||||
{
|
||||
class RAMTileRenderer {
|
||||
private:
|
||||
//! @brief ram to render
|
||||
std::shared_ptr<Ram::Ram> _ram;
|
||||
//! @brief The size to render in the ram
|
||||
int _renderSize;
|
||||
//! @brief The number of tile columns to display
|
||||
int _nbColumns;
|
||||
//! @brief Bytes to skip from the start of the ram
|
||||
int _ramOffset;
|
||||
//! @brief The actual bpp to render
|
||||
int _bpp;
|
||||
//! @brief The class tha actually render the tile
|
||||
PPU::TileRenderer _tileRenderer;
|
||||
public:
|
||||
//! @brief internal buffer
|
||||
std::array<std::array<uint32_t, 1024>, 1024> buffer;
|
||||
//! @brief Set the palette to use for render (index of palette)
|
||||
void setPaletteIndex(int paletteIndex);
|
||||
//! @brief Set the ram to look for color references
|
||||
void setCgram(std::shared_ptr<Ram::Ram> ram);
|
||||
//! @brief Set the bpp to render graphics
|
||||
void setBpp(int bpp);
|
||||
//! @brief Set the number of maximum columns
|
||||
void setNbColumns(int nbColumns);
|
||||
//! @brief Set the size of ram to render
|
||||
void setRenderSize(int size);
|
||||
//! @brief The ram to render
|
||||
void setRam(std::shared_ptr<Ram::Ram> ram);
|
||||
//! @brief Set the ram offset
|
||||
void setRamOffset(int offset);
|
||||
//! @brief Get the current bpp
|
||||
int getBpp() const;
|
||||
//! @brief Get the index of the current palette used
|
||||
int getPaletteIndex() const;
|
||||
//! @brief Get the numbr of maximum tile columns to render
|
||||
int getNbColumns() const;
|
||||
//! @brief render the selected ram
|
||||
void render();
|
||||
//! @brief ctor
|
||||
RAMTileRenderer();
|
||||
//! @brief copy ctor
|
||||
RAMTileRenderer(const RAMTileRenderer &) = default;
|
||||
//! @brief dtor
|
||||
~RAMTileRenderer() = default;
|
||||
//! @brief assignment operator
|
||||
RAMTileRenderer &operator=(const RAMTileRenderer &) = default;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
//
|
||||
// Created by cbihan on 5/7/21.
|
||||
//
|
||||
|
||||
namespace ComSquare::Renderer
|
||||
{
|
||||
class QtFullSFML;
|
||||
}
|
||||
|
||||
#include "Renderer/QtRenderer/QtSFML.hpp"
|
||||
#include "TileViewer.hpp"
|
||||
#include "SNES.hpp"
|
||||
#include <QColor>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <QtWidgets/QTableWidget>
|
||||
#include "Utility/Utility.hpp"
|
||||
#include "RAMTileRenderer.hpp"
|
||||
#include "PPU/PPU.hpp"
|
||||
|
||||
namespace ComSquare::Debugger
|
||||
{
|
||||
TileViewer::TileViewer(SNES &snes, ComSquare::PPU::PPU &ppu)
|
||||
: _window(new ClosableWindow<TileViewer>(*this, &TileViewer::disableViewer)),
|
||||
_snes(snes),
|
||||
_ui(),
|
||||
_ppu(ppu),
|
||||
_ramTileRenderer()
|
||||
{
|
||||
this->_ramTileRenderer.setRam(ppu.vram);
|
||||
this->_ramTileRenderer.setCgram(ppu.cgram);
|
||||
this->_window->setContextMenuPolicy(Qt::NoContextMenu);
|
||||
this->_window->setAttribute(Qt::WA_QuitOnClose, false);
|
||||
this->_window->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
this->_ui.setupUi(this->_window);
|
||||
this->_sfWidget = std::make_unique<Renderer::QtSFMLTileRenderer>(this->_ui.widget_sfml);
|
||||
QMainWindow::connect(this->_ui.NbColumns, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int nb) -> void { this->setNbColumns(nb); });
|
||||
QMainWindow::connect(this->_ui.ByteSize, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int nb) -> void { this->setRenderSize(nb); });
|
||||
QMainWindow::connect(this->_ui.Address, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int nb) -> void { this->setRamOffset(nb); });
|
||||
QMainWindow::connect(this->_ui.PaletteIndex, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int nb) -> void { this->setPaletteIndex(nb); });
|
||||
QMainWindow::connect(this->_ui.BppFormat, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) -> void { this->_bppChangeUIHandler(index); });
|
||||
|
||||
// used to setup ui restrictions
|
||||
this->setBpp(this->getBpp());
|
||||
this->_window->show();
|
||||
this->internalUpdate();
|
||||
}
|
||||
|
||||
void TileViewer::disableViewer()
|
||||
{
|
||||
this->_snes.disableTileViewerDebugging();
|
||||
}
|
||||
|
||||
void TileViewer::focus()
|
||||
{
|
||||
this->_window->activateWindow();
|
||||
}
|
||||
|
||||
bool TileViewer::isDebugger()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t TileViewer::read(uint8_t addr)
|
||||
{
|
||||
return this->_ppu.cgramRead(addr);
|
||||
}
|
||||
|
||||
void TileViewer::setPaletteIndex(int paletteIndex)
|
||||
{
|
||||
this->_ramTileRenderer.setPaletteIndex(paletteIndex);
|
||||
this->internalUpdate();
|
||||
}
|
||||
|
||||
void TileViewer::setBpp(int bpp)
|
||||
{
|
||||
this->_ui.PaletteIndex->setDisabled(bpp > 4);
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
this->_ui.PaletteIndex->setValue(0);
|
||||
break;
|
||||
case 4:
|
||||
this->_ui.PaletteIndex->setMaximum(15);
|
||||
if (this->_ui.PaletteIndex->value() > 15) {
|
||||
this->_ui.PaletteIndex->setValue(15);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
bpp = 2;
|
||||
this->_ui.PaletteIndex->setMaximum(63);
|
||||
break;
|
||||
}
|
||||
this->_ramTileRenderer.setBpp(bpp);
|
||||
this->internalUpdate();
|
||||
}
|
||||
|
||||
void TileViewer::setNbColumns(int nbColumns)
|
||||
{
|
||||
this->_ramTileRenderer.setNbColumns(nbColumns);
|
||||
this->internalUpdate();
|
||||
}
|
||||
|
||||
void TileViewer::setRenderSize(int size)
|
||||
{
|
||||
this->_ramTileRenderer.setRenderSize(size);
|
||||
this->internalUpdate();
|
||||
}
|
||||
|
||||
int TileViewer::getBpp() const
|
||||
{
|
||||
return this->_ramTileRenderer.getBpp();
|
||||
}
|
||||
|
||||
int TileViewer::getPaletteIndex() const
|
||||
{
|
||||
return this->_ramTileRenderer.getPaletteIndex();
|
||||
}
|
||||
|
||||
int TileViewer::getNbColumns() const
|
||||
{
|
||||
return this->_ramTileRenderer.getNbColumns();
|
||||
}
|
||||
|
||||
void TileViewer::internalUpdate()
|
||||
{
|
||||
this->_ramTileRenderer.render();
|
||||
this->_sfWidget->buffer = this->_ramTileRenderer.buffer;
|
||||
}
|
||||
|
||||
void TileViewer::setRamOffset(int offset)
|
||||
{
|
||||
this->_ramTileRenderer.setRamOffset(offset);
|
||||
this->internalUpdate();
|
||||
}
|
||||
|
||||
void TileViewer::_bppChangeUIHandler(int index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0: return this->setBpp(2);
|
||||
case 1: return this->setBpp(4);
|
||||
case 2: return this->setBpp(8);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// TODO error handling
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// Created by cbihan on 5/7/21.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ComSquare::PPU
|
||||
{
|
||||
class PPU;
|
||||
}
|
||||
|
||||
#include <QtCore/QSortFilterProxyModel>
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <array>
|
||||
#include "PPU/PPU.hpp"
|
||||
#include "Debugger/ClosableWindow.hpp"
|
||||
#include "Renderer/QtRenderer/QtSfmlTileRenderer.hpp"
|
||||
#include "../../../ui/ui_tileView.h"
|
||||
#include "Ram/Ram.hpp"
|
||||
#include "RAMTileRenderer.hpp"
|
||||
|
||||
namespace ComSquare::Debugger
|
||||
{
|
||||
|
||||
//! @brief window that allow the user to view all data going through the memory bus.
|
||||
class TileViewer : public QObject {
|
||||
private:
|
||||
//! @brief The QT window for this debugger.
|
||||
ClosableWindow<TileViewer> *_window;
|
||||
//! @brief A reference to the snes (to disable the debugger).
|
||||
SNES &_snes;
|
||||
//! @brief A widget that contain the whole UI.
|
||||
Ui::TileViewer _ui;
|
||||
//! @brief A reference to the ppu
|
||||
ComSquare::PPU::PPU &_ppu;
|
||||
//! @brief the window
|
||||
std::unique_ptr<Renderer::QtSFMLTileRenderer> _sfWidget;
|
||||
//! @brief The ram tile renderer
|
||||
RAMTileRenderer _ramTileRenderer;
|
||||
//! @brief Change the bpp from the index given by the ui (QT combo box)
|
||||
void _bppChangeUIHandler(int index);
|
||||
public:
|
||||
//! @brief Called when the window is closed. Turn off the debugger.
|
||||
void disableViewer();
|
||||
//! @brief ctor
|
||||
explicit TileViewer(SNES &snes, ComSquare::PPU::PPU &ppu);
|
||||
//! @brief copy ctor
|
||||
TileViewer(const TileViewer &) = delete;
|
||||
//! @brief dtor
|
||||
~TileViewer() override = default;
|
||||
//! @brief assignment operator
|
||||
TileViewer &operator=(const TileViewer &) = delete;
|
||||
|
||||
//! @brief Read data at the CGRAM address send it to the debugger.
|
||||
//! @param addr The address to read from.
|
||||
//! @return The color value in BGR, looks like this xbbbbbgggggrrrrr.
|
||||
uint16_t read(uint8_t addr);
|
||||
//! @brief Focus the debugger's window.
|
||||
void focus();
|
||||
//! @brief Return true if the Bus is overloaded with debugging features.
|
||||
bool isDebugger();
|
||||
//! @brief Set the palette to use for render (index of palette)
|
||||
void setPaletteIndex(int paletteIndex);
|
||||
//! @brief Set the bpp to render graphics
|
||||
void setBpp(int bpp);
|
||||
//! @brief Set the number of maximum columns
|
||||
void setNbColumns(int nbColumns);
|
||||
//! @brief Set the size of ram to render
|
||||
void setRenderSize(int size);
|
||||
//! @brief Set the ram offset
|
||||
void setRamOffset(int offset);
|
||||
//! @brief Get the current bpp
|
||||
int getBpp() const;
|
||||
//! @brief Get the index of the current palette used
|
||||
int getPaletteIndex() const;
|
||||
//! @brief Get the numbr of maximum tile columns to render
|
||||
int getNbColumns() const;
|
||||
//! @brief Update the tile renderer
|
||||
void internalUpdate();
|
||||
|
||||
};
|
||||
}
|
||||
+38
-93
@@ -6,6 +6,8 @@
|
||||
#include "PPU.hpp"
|
||||
#include "Background.hpp"
|
||||
#include <cmath>
|
||||
#include "Tile.hpp"
|
||||
#include "PPUUtils.hpp"
|
||||
#include "Models/Vector2.hpp"
|
||||
|
||||
namespace ComSquare::PPU
|
||||
@@ -21,10 +23,13 @@ namespace ComSquare::PPU
|
||||
_tilesetAddress(ppu.getTilesetAddress(backGroundNumber)),
|
||||
_priority(hasPriority),
|
||||
_bgNumber(backGroundNumber),
|
||||
_tileBuffer({{{0}}}),
|
||||
_vram(ppu.vram),
|
||||
_cgram(ppu.cgram),
|
||||
buffer({{{0}}})
|
||||
{
|
||||
this->_tileRenderer.setRam(this->_vram);
|
||||
this->_tileRenderer.setCgram(this->_cgram);
|
||||
}
|
||||
|
||||
void Background::renderBackground()
|
||||
@@ -36,7 +41,7 @@ namespace ComSquare::PPU
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(i == 1 && this->_tileMapsConfig.x == 1) && !(i > 1 && this->_tileMapsConfig.y == 1)) {
|
||||
drawBasicTileMap(vramAddress, offset);
|
||||
_drawBasicTileMap(vramAddress, offset);
|
||||
}
|
||||
vramAddress += TileMapByteSize;
|
||||
offset.x += NbCharacterWidth * this->_characterNbPixels.x;
|
||||
@@ -47,32 +52,42 @@ namespace ComSquare::PPU
|
||||
}
|
||||
}
|
||||
|
||||
void Background::drawBgTile(uint16_t data, Vector2<int> pos)
|
||||
void Background::_drawBgTile(uint16_t data, Vector2<int> pos)
|
||||
{
|
||||
uint16_t graphicAddress;
|
||||
union TileMapData tileData;
|
||||
std::vector<uint16_t> palette;
|
||||
int index = 0;
|
||||
uint8_t reference = 0;
|
||||
uint32_t color = 0;
|
||||
|
||||
tileData.raw = data;
|
||||
palette = getPalette(tileData.palette);
|
||||
|
||||
if (tileData.tilePriority != this->_priority)
|
||||
return;
|
||||
|
||||
uint16_t graphicAddress;
|
||||
Vector2i tileOffset = {0, 0};
|
||||
// X horizontal
|
||||
// Y vertical
|
||||
graphicAddress = this->_tilesetAddress + (tileData.posY * NbTilePerRow * this->_bpp * TileBaseByteSize) + (tileData.posX * this->_bpp * TileBaseByteSize);
|
||||
|
||||
this->_tileRenderer.setPaletteIndex(tileData.palette);
|
||||
for (int i = 0; i < this->_characterNbPixels.y; i += Tile::NbPixelsHeight) {
|
||||
for (int j = 0; j < this->_characterNbPixels.x; j += Tile::NbPixelsWidth) {
|
||||
graphicAddress = this->_tilesetAddress +
|
||||
((tileData.posY + tileOffset.y) * NbTilePerRow * this->_bpp * Tile::BaseByteSize) +
|
||||
((tileData.posX + tileOffset.x) * this->_bpp * Tile::BaseByteSize);
|
||||
this->_tileRenderer.render(graphicAddress);
|
||||
merge2DArray(this->_tileBuffer, this->_tileRenderer.buffer, {j, i});
|
||||
tileOffset.x += 1;
|
||||
}
|
||||
tileOffset.x = 0;
|
||||
tileOffset.y += 1;
|
||||
}
|
||||
|
||||
// todo check why i need to invert vertical and horizontal flips
|
||||
if (tileData.verticalFlip)
|
||||
HFlipArray(this->_tileBuffer, {this->_characterNbPixels.x, this->_characterNbPixels.y});
|
||||
if (tileData.horizontalFlip)
|
||||
VFlipArray(this->_tileBuffer, {this->_characterNbPixels.x, this->_characterNbPixels.y});
|
||||
for (int i = 0; i < this->_characterNbPixels.y; i++) {
|
||||
index = i * this->_characterNbPixels.x;
|
||||
if (tileData.verticalFlip)
|
||||
index = (this->_characterNbPixels.y - 1 - i) * this->_characterNbPixels.x;
|
||||
if (tileData.horizontalFlip)
|
||||
index += this->_characterNbPixels.x - 1;
|
||||
for (int j = 0; j < this->_characterNbPixels.x; j++) {
|
||||
reference = getPixelReferenceFromTile(graphicAddress, index);
|
||||
color = getRealColor(palette[reference]);
|
||||
if (tileData.tilePriority == this->_priority) // reference 0 is considered as transparency
|
||||
this->buffer[pos.x][pos.y] = (reference) ? color : 0;
|
||||
index += (tileData.horizontalFlip) ? -1 : 1;
|
||||
this->buffer[pos.x][pos.y] = this->_tileBuffer[i][j];
|
||||
pos.x++;
|
||||
}
|
||||
pos.x -= this->_characterNbPixels.x;
|
||||
@@ -80,74 +95,7 @@ namespace ComSquare::PPU
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint16_t> Background::getPalette(int nbPalette)
|
||||
{
|
||||
uint8_t nbColors = std::pow(2, this->_bpp);
|
||||
uint16_t addr = nbPalette * this->_bpp * this->_bpp * 2; // 2 because it's 2 addr for 1 color
|
||||
std::vector<uint16_t> palette(nbColors);
|
||||
|
||||
switch (this->_ppu.getBgMode()) {
|
||||
case 0:
|
||||
addr += (this->_bgNumber - 1) * (4 * 8) * 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nbColors; i++) {
|
||||
palette[i] = this->_cgram->read(addr);
|
||||
palette[i] += this->_cgram->read(addr + 1) << 8U;
|
||||
addr += 2;
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
uint8_t Background::getPixelReferenceFromTile(uint16_t tileAddress, uint8_t pixelIndex)
|
||||
{
|
||||
uint8_t row = pixelIndex / this->_characterNbPixels.x;
|
||||
uint8_t column = pixelIndex % this->_characterNbPixels.y;
|
||||
|
||||
if (row >= TileNbPixelsHeight) {
|
||||
tileAddress += 0x80 * this->_bpp;
|
||||
row -= TileNbPixelsHeight;
|
||||
}
|
||||
if (column >= TileNbPixelsWidth) {
|
||||
tileAddress += 0x8 * this->_bpp;
|
||||
column -= TileNbPixelsWidth;
|
||||
}
|
||||
// TODO might not work with 8 bpp must check
|
||||
tileAddress += 2 * row;
|
||||
|
||||
return this->getPixelReferenceFromTileRow(tileAddress, column);
|
||||
}
|
||||
|
||||
uint8_t Background::getPixelReferenceFromTileRow(uint16_t tileAddress, uint8_t pixelIndex)
|
||||
{
|
||||
uint8_t highByte = this->_vram->read(tileAddress % VRAMSIZE);
|
||||
uint8_t lowByte = this->_vram->read((tileAddress + 1) % VRAMSIZE);
|
||||
uint8_t secondHighByte;
|
||||
uint8_t secondLowByte;
|
||||
uint16_t result = 0;
|
||||
uint8_t shift = TileNbPixelsWidth - 1U - pixelIndex;
|
||||
|
||||
switch (this->_bpp) {
|
||||
case 8:
|
||||
return highByte;
|
||||
case 4:
|
||||
secondHighByte = this->_vram->read((tileAddress + 16) % VRAMSIZE);
|
||||
secondLowByte = this->_vram->read((tileAddress + 17) % VRAMSIZE);
|
||||
result = ((secondHighByte & (1U << shift)) | ((secondLowByte & (1U << shift)) << 1U));
|
||||
result = (shift - 2 >= 0) ? result >> (shift - 2) : result << ((shift - 2) * -1);
|
||||
FALLTHROUGH
|
||||
case 2:
|
||||
result += ((highByte & (1U << shift)) | ((lowByte & (1U << shift)) << 1U)) >> shift;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Background::drawBasicTileMap(uint16_t baseAddress, Vector2<int> offset)
|
||||
void Background::_drawBasicTileMap(uint16_t baseAddress, Vector2<int> offset)
|
||||
{
|
||||
uint16_t tileMapValue = 0;
|
||||
Vector2<int> pos(0, 0);
|
||||
@@ -157,7 +105,8 @@ namespace ComSquare::PPU
|
||||
// TODO function to read 2 bytes (LSB order or bits reversed)
|
||||
tileMapValue = this->_vram->read(vramAddress);
|
||||
tileMapValue += this->_vram->read(vramAddress + 1) << 8U;
|
||||
drawBgTile(tileMapValue, {(pos.x * this->_characterNbPixels.x) + offset.x, (pos.y * this->_characterNbPixels.y) + offset.y});
|
||||
_drawBgTile(tileMapValue, {(pos.x * this->_characterNbPixels.x) + offset.x,
|
||||
(pos.y * this->_characterNbPixels.y) + offset.y});
|
||||
vramAddress += 2;
|
||||
if (pos.x % 31 == 0 && pos.x) {
|
||||
pos.y++;
|
||||
@@ -189,6 +138,7 @@ namespace ComSquare::PPU
|
||||
this->_bpp = bpp;
|
||||
else
|
||||
this->_bpp = 2;
|
||||
this->_tileRenderer.setBpp(this->_bpp);
|
||||
}
|
||||
|
||||
void Background::setTilemaps(Vector2<int> tileMaps)
|
||||
@@ -196,11 +146,6 @@ namespace ComSquare::PPU
|
||||
this->_tileMapsConfig = tileMaps;
|
||||
}
|
||||
|
||||
void Background::setBgNumber(int bgNumber)
|
||||
{
|
||||
this->_bgNumber = bgNumber;
|
||||
}
|
||||
|
||||
int Background::getBgNumber() const
|
||||
{
|
||||
return this->_bgNumber;
|
||||
|
||||
+10
-35
@@ -2,19 +2,16 @@
|
||||
// Created by cbihan on 5/14/20.
|
||||
//
|
||||
|
||||
#ifndef COMSQUARE_BACKGROUND_HPP
|
||||
#define COMSQUARE_BACKGROUND_HPP
|
||||
#pragma once
|
||||
|
||||
#include <stdint-gcc.h>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "../Models/Vector2.hpp"
|
||||
#include "TileRenderer.hpp"
|
||||
#include "../Ram/Ram.hpp"
|
||||
#include "PPU.hpp"
|
||||
|
||||
//! @brief Transform SNES color code BGR to uint32_t RGB
|
||||
uint32_t getRealColor(uint16_t color);
|
||||
|
||||
namespace ComSquare::PPU
|
||||
{
|
||||
class PPU;
|
||||
@@ -24,13 +21,6 @@ namespace ComSquare::PPU
|
||||
static constexpr int NbCharacterWidth = 32;
|
||||
//! @brief The number of character a TileMap has in height
|
||||
static constexpr int NbCharacterHeight = 32;
|
||||
//! @brief The minimum number of pixel a tile can have in width
|
||||
static constexpr int TileNbPixelsWidth = 8;
|
||||
//! @brief The minimum number of pixel a tile can have in height
|
||||
static constexpr int TileNbPixelsHeight = 8;
|
||||
//! @brief The number of bytes used by a range of pixels (1 pixel per byte)
|
||||
//! @note Used like: bpp * TileBaseByteSize to get the size of byte of 1 row of pixels
|
||||
static constexpr unsigned TileBaseByteSize = 8;
|
||||
//! @brief The number of rows in one line of VRAM
|
||||
//! @note If you're lost by this description, open a tile viewer in an emulator, and set the number of tiles in width to 16 graphics
|
||||
static constexpr unsigned NbTilePerRow = 16;
|
||||
@@ -59,30 +49,20 @@ namespace ComSquare::PPU
|
||||
bool _priority;
|
||||
//! @brief The bg number (used to get the corresponding scroll)
|
||||
int _bgNumber;
|
||||
//! @brief Class that actually render a tile
|
||||
TileRenderer _tileRenderer;
|
||||
//! @brief Buffer if we have tiles that are more than 8x8
|
||||
std::array<std::array<uint32_t, 16>, 16> _tileBuffer;
|
||||
//! @brief the access to vram
|
||||
std::shared_ptr<Ram::Ram> _vram;
|
||||
//! @brief The access to cgram
|
||||
std::shared_ptr<Ram::Ram> _cgram;
|
||||
//! @brief Draw a tile on the screen at x y pos
|
||||
void drawBgTile(uint16_t data, Vector2<int> pos);
|
||||
//! @brief Get a palette from the number of the palette
|
||||
//! @param nbPalette The palette number (0 - 7)
|
||||
//! @return The array of color of the palette
|
||||
std::vector<uint16_t> getPalette(int nbPalette);
|
||||
//! @brief Get the color reference of a pixel from the address of the row
|
||||
//! @param tileAddress The address of the line of pixel
|
||||
//! @param pixelIndex The index of the pixel (0 - 7)
|
||||
//! @return The color Reference
|
||||
uint8_t getPixelReferenceFromTileRow(uint16_t tileAddress, uint8_t pixelIndex);
|
||||
//! @brief Get the color pixel reference from the tile address
|
||||
//! @param tileAddress The starting address of the tile
|
||||
//! @param pixelIndex The index of the pixel (0 - 255)
|
||||
//! @return The color reference
|
||||
uint8_t getPixelReferenceFromTile(uint16_t tileAddress, uint8_t pixelIndex);
|
||||
void _drawBgTile(uint16_t data, Vector2<int> pos);
|
||||
//! @brief draw a tileMap 32x32 starting at baseAddress
|
||||
//! @param baseAddress The starting address of the tileMap
|
||||
//! @param offset The rendering offeset in pixels
|
||||
void drawBasicTileMap(uint16_t baseAddress, Vector2<int> offset);
|
||||
void _drawBasicTileMap(uint16_t baseAddress, Vector2<int> offset);
|
||||
public:
|
||||
//! @brief The size of the background (x, y)
|
||||
Vector2<unsigned> backgroundSize;
|
||||
@@ -105,9 +85,7 @@ namespace ComSquare::PPU
|
||||
//! @brief setter for private variable _tileMaps
|
||||
//! @param tileMaps The tileMaps to set
|
||||
void setTilemaps(Vector2<int> tileMaps);
|
||||
//! @brief set the Background number
|
||||
//! @param bgNumber the new Background Number
|
||||
void setBgNumber(int bgNumber);
|
||||
|
||||
//! @brief Get the BackGround Number
|
||||
//! @return the current Background number
|
||||
int getBgNumber() const;
|
||||
@@ -127,7 +105,4 @@ namespace ComSquare::PPU
|
||||
//! @brief Delete assignment operator
|
||||
Background &operator=(const Background &) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //COMSQUARE_BACKGROUND_HPP
|
||||
}
|
||||
+25
-17
@@ -5,10 +5,11 @@
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
#include "PPU.hpp"
|
||||
#include "../Exceptions/NotImplementedException.hpp"
|
||||
#include "../Exceptions/InvalidAddress.hpp"
|
||||
#include "../Ram/Ram.hpp"
|
||||
#include "../Models/Vector2.hpp"
|
||||
#include "Exceptions/NotImplementedException.hpp"
|
||||
#include "Exceptions/InvalidAddress.hpp"
|
||||
#include "Ram/Ram.hpp"
|
||||
#include "Models/Vector2.hpp"
|
||||
#include "Debugger/TileViewer/RAMTileRenderer.hpp"
|
||||
#include <random>
|
||||
|
||||
namespace ComSquare::PPU
|
||||
@@ -43,7 +44,7 @@ namespace ComSquare::PPU
|
||||
this->cgram->write(67, 0x7F);
|
||||
|
||||
//tiles
|
||||
int vram_test[] = {
|
||||
/* int vram_test[] = {
|
||||
00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
|
||||
@@ -74,17 +75,17 @@ namespace ComSquare::PPU
|
||||
00,0x03,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0c,0x00,0x18,0x00,0xf0,0x00,0xe0,
|
||||
00,0x00,0x00,0x00,0x80,0x00,0xc0,0x00,0xe0,0x00,0xf0,0x00,0xf8,0x00,0xfc,0x00,
|
||||
00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x00,0x0f,00,0x1f,00,0x3f,00, -1
|
||||
};
|
||||
/*int *cgram_test = get_dump_cgram();
|
||||
};*/
|
||||
int *cgram_test = get_dump_cgram();
|
||||
for (int i = 0; cgram_test[i] != -1; i++) {
|
||||
this->cgram->write(i, cgram_test[i]);
|
||||
}*/
|
||||
}
|
||||
|
||||
// int *vram_test = get_dump_vram();
|
||||
int *vram_test = get_dump_vram();
|
||||
for (int i = 0; vram_test[i] != -1; i++) {
|
||||
this->vram->write(i, vram_test[i]);
|
||||
}
|
||||
int vram_test_2[] = {8, 00, 02, 00, 0x0A, 00, 02, 00, 0x0A, 00, 00, 00, 00, 00, 00, -1};
|
||||
/* int vram_test_2[] = {8, 00, 02, 00, 0x0A, 00, 02, 00, 0x0A, 00, 00, 00, 00, 00, 00, -1};
|
||||
for (int i = 0; vram_test_2[i] != -1; i++) {
|
||||
this->vram->write(i + 0x8000, vram_test_2[i]);
|
||||
}
|
||||
@@ -143,8 +144,8 @@ namespace ComSquare::PPU
|
||||
//this->_registers._bgofs[3].raw = 0x03DF;
|
||||
this->_registers._t[0].enableWindowDisplayBg1 = true;
|
||||
this->_registers._t[0].enableWindowDisplayBg2 = true;
|
||||
*/
|
||||
|
||||
/*
|
||||
//registers aladin
|
||||
|
||||
this->_registers._bgmode.bgMode = 1;
|
||||
@@ -199,12 +200,12 @@ namespace ComSquare::PPU
|
||||
this->_registers._t[0].enableWindowDisplayBg2 = true;
|
||||
this->_registers._t[0].enableWindowDisplayBg3 = true;
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
uint8_t PPU::read(uint24_t addr)
|
||||
{
|
||||
//return 0;
|
||||
return 0;
|
||||
switch (addr) {
|
||||
case PpuRegisters::mpyl:
|
||||
return this->_registers._mpy.mpyl;
|
||||
@@ -249,7 +250,7 @@ namespace ComSquare::PPU
|
||||
|
||||
void PPU::write(uint24_t addr, uint8_t data)
|
||||
{
|
||||
//return;
|
||||
return;
|
||||
switch (addr) {
|
||||
case PpuRegisters::inidisp:
|
||||
this->_registers._inidisp.raw = data;
|
||||
@@ -466,6 +467,7 @@ namespace ComSquare::PPU
|
||||
{
|
||||
(void)cycles;
|
||||
|
||||
|
||||
this->renderMainAndSubScreen();
|
||||
this->add_buffer(this->_screen, this->_subScreen);
|
||||
this->add_buffer(this->_screen, this->_mainScreen);
|
||||
@@ -477,6 +479,10 @@ namespace ComSquare::PPU
|
||||
}
|
||||
}
|
||||
this->_renderer.drawScreen();
|
||||
for (auto &i : this->_mainScreen)
|
||||
i.fill(0XFF);
|
||||
for (auto &i : this->_subScreen)
|
||||
i.fill(0XFF);
|
||||
}
|
||||
|
||||
std::string PPU::getName() const
|
||||
@@ -806,13 +812,15 @@ namespace ComSquare::PPU
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t DEST_SIZE, std::size_t SRC_SIZE>
|
||||
void PPU::add_buffer(std::array<std::array<uint32_t, DEST_SIZE>, DEST_SIZE> &bufferDest, std::array<std::array<uint32_t, SRC_SIZE>, SRC_SIZE> &bufferSrc)
|
||||
template <std::size_t DEST_SIZE_X, std::size_t DEST_SIZE_Y, std::size_t SRC_SIZE_X, std::size_t SRC_SIZE_Y>
|
||||
void PPU::add_buffer(std::array<std::array<uint32_t, DEST_SIZE_Y>, DEST_SIZE_X> &bufferDest,
|
||||
const std::array<std::array<uint32_t, SRC_SIZE_Y>, SRC_SIZE_X> &bufferSrc,
|
||||
const Vector2<int> &offset)
|
||||
{
|
||||
for (unsigned long i = 0; i < bufferSrc.size(); i++) {
|
||||
for (unsigned long j = 0; j < bufferSrc[i].size(); j++) {
|
||||
if (bufferSrc[i][j] > 0xFF) // 0xFF correspond to a black pixel with full brightness
|
||||
bufferDest[i][j] = bufferSrc[i][j];
|
||||
bufferDest[i + offset.x ][j + offset.y] = bufferSrc[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-8
@@ -6,17 +6,18 @@
|
||||
#define COMSQUARE_PPU_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "../Memory/AMemory.hpp"
|
||||
#include "../Memory/MemoryBus.hpp"
|
||||
#include "../Renderer/IRenderer.hpp"
|
||||
#include "../Ram/Ram.hpp"
|
||||
#include "../Models/Vector2.hpp"
|
||||
#include "Memory/AMemory.hpp"
|
||||
#include "Memory/MemoryBus.hpp"
|
||||
#include "Renderer/IRenderer.hpp"
|
||||
#include "Ram/Ram.hpp"
|
||||
#include "Models/Vector2.hpp"
|
||||
#include "Background.hpp"
|
||||
#include "PPUUtils.hpp"
|
||||
#include "Debugger/TileViewer/RAMTileRenderer.hpp"
|
||||
|
||||
#define FALLTHROUGH __attribute__((fallthrough));
|
||||
|
||||
// TODO check if it usefull to have defines instead of constepxr
|
||||
// TODO check if it useful to have defines instead of constexpr
|
||||
#define VRAMSIZE 65536
|
||||
#define CGRAMSIZE 512
|
||||
#define OAMRAMSIZE 544
|
||||
@@ -569,6 +570,7 @@ namespace ComSquare::PPU
|
||||
uint16_t _vramReadBuffer = 0;
|
||||
//! @brief Struct that contain all necessary vars for the use of the registers
|
||||
struct PpuState _ppuState;
|
||||
|
||||
public:
|
||||
|
||||
explicit PPU(Renderer::IRenderer &renderer);
|
||||
@@ -618,8 +620,10 @@ namespace ComSquare::PPU
|
||||
//! @brief Render the Main and sub screen correctly
|
||||
void renderMainAndSubScreen();
|
||||
//! @brief Add a bg buffer to another buffer
|
||||
template <std::size_t DEST_SIZE, std::size_t SRC_SIZE>
|
||||
void add_buffer(std::array<std::array<uint32_t, DEST_SIZE>, DEST_SIZE> &bufferDest, std::array<std::array<uint32_t, SRC_SIZE>, SRC_SIZE> &bufferSrc);
|
||||
template <std::size_t DEST_SIZE_X, std::size_t DEST_SIZE_Y, std::size_t SRC_SIZE_X, std::size_t SRC_SIZE_Y>
|
||||
void add_buffer(std::array<std::array<uint32_t, DEST_SIZE_Y>, DEST_SIZE_X> &bufferDest,
|
||||
const std::array<std::array<uint32_t, SRC_SIZE_Y>, SRC_SIZE_X> &bufferSrc,
|
||||
const Vector2<int> &offset = {0, 0});
|
||||
//! @brief Add a bg to the sub and/or main screen
|
||||
void addToMainSubScreen(Background &bg);
|
||||
//! @brief Get the current background Mode
|
||||
@@ -630,6 +634,20 @@ namespace ComSquare::PPU
|
||||
Vector2<int> getBgScroll(int bgNumber) const;
|
||||
//! @brief Allow to look the value of each write register (used by Register debugger)
|
||||
const Registers &getWriteRegisters() const;
|
||||
|
||||
template <std::size_t SRC_SIZE_Y, std::size_t SRC_SIZE_X>
|
||||
void add_buffer(const std::array<std::array<uint32_t, SRC_SIZE_Y>, SRC_SIZE_X> &buffer,
|
||||
const Vector2<int> &offset = {0, 0})
|
||||
{
|
||||
for (auto &i : this->_screen)
|
||||
i.fill(0XFF);
|
||||
for (unsigned long i = 0; i < buffer.size(); i++) {
|
||||
for (unsigned long j = 0; j < buffer[i].size(); j++) {
|
||||
if (buffer[i][j] > 0xFF) // 0xFF correspond to a black pixel with full brightness
|
||||
this->_screen[i + offset.x][j + offset.y] = buffer[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Transform SNES color code BGR to uint32_t RGB
|
||||
|
||||
@@ -9,16 +9,11 @@ namespace ComSquare::PPU
|
||||
|
||||
uint32_t getRealColor(uint16_t color)
|
||||
{
|
||||
uint8_t blue;
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint32_t pixelTmp;
|
||||
uint8_t blue = (color & 0x7D00U) >> 10U;
|
||||
uint8_t green = (color & 0x03E0U) >> 5U;
|
||||
uint8_t red = (color & 0x001FU);
|
||||
uint32_t pixelTmp = 0xFF;
|
||||
|
||||
blue = (color & 0x7D00U) >> 10U;
|
||||
green = (color & 0x03E0U) >> 5U;
|
||||
red = (color & 0x001FU);
|
||||
|
||||
pixelTmp = 0xFF;
|
||||
pixelTmp += (red * 255U / 31U) << 24U;
|
||||
pixelTmp += (green * 255U / 31U) << 16U;
|
||||
pixelTmp += (blue * 255U / 31U) << 8U;
|
||||
|
||||
@@ -6,9 +6,15 @@
|
||||
#define COMSQUARE_PPU_UTILS_HPP
|
||||
|
||||
#include <stdint-gcc.h>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
#include "Models//Vector2.hpp"
|
||||
|
||||
namespace ComSquare::PPU
|
||||
{
|
||||
|
||||
//! @brief Transform SNES color code BGR to uint32_t RGB
|
||||
uint32_t getRealColor(uint16_t color);
|
||||
//! @brief Used to parse easily VRAM Tile information
|
||||
union TileMapData {
|
||||
struct {
|
||||
@@ -36,5 +42,35 @@ namespace ComSquare::PPU
|
||||
uint8_t hScrollPrevValue;
|
||||
};
|
||||
|
||||
template <std::size_t DEST_SIZE_Y, std::size_t DEST_SIZE_X, std::size_t SRC_SIZE_Y, std::size_t SRC_SIZE_X>
|
||||
void merge2DArray(std::array<std::array<uint32_t, DEST_SIZE_X>, DEST_SIZE_Y> &bufferDest,
|
||||
const std::array<std::array<uint32_t, SRC_SIZE_X>, SRC_SIZE_Y> &bufferSrc,
|
||||
const Vector2<int> &offset = {0, 0})
|
||||
{
|
||||
for (unsigned long i = 0; i < bufferSrc.size(); i++) {
|
||||
for (unsigned long j = 0; j < bufferSrc[i].size(); j++) {
|
||||
bufferDest[i + offset.y][j + offset.x] = bufferSrc[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t SRC_SIZE_Y, std::size_t SRC_SIZE_X>
|
||||
void VFlipArray(std::array<std::array<uint32_t, SRC_SIZE_X>, SRC_SIZE_Y> &array,
|
||||
const Vector2<int> &size,
|
||||
const Vector2<int> &offset = {0, 0})
|
||||
{
|
||||
for (int i = offset.y; i < offset.y + size.y; i++) {
|
||||
std::reverse(array[i].begin() + offset.x, array[i].begin() + offset.x + size.x);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t SRC_SIZE_Y, std::size_t SRC_SIZE_X>
|
||||
void HFlipArray(std::array<std::array<uint32_t, SRC_SIZE_X>, SRC_SIZE_Y> &array,
|
||||
const Vector2<int> &size,
|
||||
const Vector2<int> &offset = {0, 0})
|
||||
{
|
||||
std::reverse(array.begin() + offset.x, array.begin() + offset.x + size.x);
|
||||
}
|
||||
|
||||
}
|
||||
#endif //COMSQUARE_PPU_UTILS_HPP
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Created by cbihan on 25/05/2021.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ComSquare::PPU
|
||||
{
|
||||
//! @brief Info on tile struct
|
||||
struct Tile
|
||||
{
|
||||
//! @brief The number of pixel a base tile can have in width
|
||||
static constexpr int NbPixelsWidth = 8;
|
||||
//! @brief The number of pixel a base tile can have in height
|
||||
static constexpr int NbPixelsHeight = 8;
|
||||
//! @brief A base tile size in byte is 0x8
|
||||
//! @note Used like: bpp * BaseByteSize to get the byte size of 1 tile
|
||||
static constexpr int BaseByteSize = 0x8;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// Created by cbihan on 24/05/2021.
|
||||
//
|
||||
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include "TileRenderer.hpp"
|
||||
#include "PPU/PPU.hpp"
|
||||
#include "PPU/Tile.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace ComSquare::PPU
|
||||
{
|
||||
TileRenderer::TileRenderer()
|
||||
: _ram(nullptr),
|
||||
_cgram(nullptr),
|
||||
_bpp(2),
|
||||
_paletteIndex(0),
|
||||
buffer({{{0}}})
|
||||
{
|
||||
}
|
||||
|
||||
void TileRenderer::setRam(std::shared_ptr<Ram::Ram> ram)
|
||||
{
|
||||
this->_ram = std::move(ram);
|
||||
}
|
||||
|
||||
void TileRenderer::render(uint16_t tileAddress)
|
||||
{
|
||||
std::vector<uint16_t> palette = this->getPalette(this->_paletteIndex);
|
||||
int it = 0;
|
||||
this->buffer = {{{0}}};
|
||||
|
||||
for (auto &row : this->buffer) {
|
||||
for (auto &pixel : row) {
|
||||
uint8_t pixelReference = this->getPixelReferenceFromTile(tileAddress, it++);
|
||||
pixel = pixelReference ? getRealColor(palette[pixelReference]) : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TileRenderer::getPixelReferenceFromTile(uint16_t tileAddress, uint8_t pixelIndex)
|
||||
{
|
||||
uint8_t row = pixelIndex / Tile::NbPixelsWidth;
|
||||
uint8_t column = pixelIndex % Tile::NbPixelsHeight;
|
||||
|
||||
if (row >= Tile::NbPixelsHeight) {
|
||||
tileAddress += 0x80 * this->_bpp;
|
||||
row -= Tile::NbPixelsHeight;
|
||||
}
|
||||
if (column >= Tile::NbPixelsWidth) {
|
||||
tileAddress += 0x8 * this->_bpp;
|
||||
column -= Tile::NbPixelsWidth;
|
||||
}
|
||||
// TODO might not work with 8 bpp must check
|
||||
tileAddress += 2 * row;
|
||||
|
||||
return this->getPixelReferenceFromTileRow(tileAddress, column);
|
||||
}
|
||||
|
||||
void TileRenderer::setPaletteIndex(int paletteIndex)
|
||||
{
|
||||
this->_paletteIndex = paletteIndex;
|
||||
}
|
||||
|
||||
void TileRenderer::setBpp(int bpp)
|
||||
{
|
||||
this->_bpp = bpp;
|
||||
}
|
||||
|
||||
uint8_t TileRenderer::read2BPPValue(uint16_t tileRowAddress, uint8_t pixelIndex)
|
||||
{
|
||||
// TODO unit test this
|
||||
size_t size = this->_ram->getSize();
|
||||
uint8_t highByte = this->_ram->read(tileRowAddress % size);
|
||||
uint8_t lowByte = this->_ram->read((tileRowAddress + 1) % size);
|
||||
uint8_t shift = 8 - 1U - pixelIndex;
|
||||
|
||||
return ((highByte & (1U << shift)) | ((lowByte & (1U << shift)) << 1U)) >> shift;
|
||||
}
|
||||
|
||||
uint8_t TileRenderer::getPixelReferenceFromTileRow(uint16_t tileRowAddress, uint8_t pixelIndex)
|
||||
{
|
||||
// TODO unit test this
|
||||
uint16_t result = 0;
|
||||
// TODO do a constexpr
|
||||
const int TileByteSizeRow = 16;
|
||||
|
||||
switch (this->_bpp) {
|
||||
case 8:
|
||||
result += this->read2BPPValue(tileRowAddress + TileByteSizeRow * 2, pixelIndex) << 4;
|
||||
result += this->read2BPPValue(tileRowAddress + TileByteSizeRow * 3, pixelIndex) << 6;
|
||||
FALLTHROUGH
|
||||
case 4:
|
||||
result += this->read2BPPValue(tileRowAddress + TileByteSizeRow, pixelIndex) << 2;
|
||||
FALLTHROUGH
|
||||
case 2:
|
||||
result += this->read2BPPValue(tileRowAddress, pixelIndex);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> TileRenderer::getPalette(int nbPalette)
|
||||
{
|
||||
// todo if needed the tile renderer could cache the palette to avoid recompute this every render
|
||||
uint16_t nbColors = std::pow(2, this->_bpp);
|
||||
uint16_t addr = nbPalette * this->_bpp * this->_bpp * 2; // 2 because it's 2 addr for 1 color
|
||||
std::vector<uint16_t> palette(nbColors);
|
||||
|
||||
for (int i = 0; i < nbColors; i++) {
|
||||
palette[i] = this->_cgram->read(addr);
|
||||
palette[i] += this->_cgram->read(addr + 1) << 8U;
|
||||
addr += 2;
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
void TileRenderer::setCgram(std::shared_ptr<Ram::Ram> ram)
|
||||
{
|
||||
this->_cgram = std::move(ram);
|
||||
}
|
||||
|
||||
int TileRenderer::getBpp() const
|
||||
{
|
||||
return this->_bpp;
|
||||
}
|
||||
|
||||
int TileRenderer::getPaletteIndex() const
|
||||
{
|
||||
return this->_paletteIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Created by cbihan on 24/05/2021.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "Ram/Ram.hpp"
|
||||
|
||||
namespace ComSquare::PPU
|
||||
{
|
||||
class TileRenderer {
|
||||
private:
|
||||
//! @brief ram to render
|
||||
std::shared_ptr<Ram::Ram> _ram;
|
||||
//! @brief cgram to access the colors
|
||||
std::shared_ptr<Ram::Ram> _cgram;
|
||||
//! @brief The bpp to use while rendering
|
||||
int _bpp;
|
||||
//! @brief The palette number to use while rendering
|
||||
int _paletteIndex;
|
||||
public:
|
||||
// todo background or ppu should have constexpr to explain it (16)
|
||||
//! @brief internal buffer max rendered tiles are 16x16
|
||||
std::array<std::array<uint32_t, 8>, 8> buffer;
|
||||
//! @brief Set the palette to use for render (index of palette)
|
||||
void setPaletteIndex(int paletteIndex);
|
||||
//! @brief Set the ram to look for color references
|
||||
void setCgram(std::shared_ptr<Ram::Ram> ram);
|
||||
//! @brief Set the bpp to render graphics
|
||||
void setBpp(int bpp);
|
||||
//! @brief The ram to render
|
||||
void setRam(std::shared_ptr<Ram::Ram> ram);
|
||||
//! @brief Get the current bpp
|
||||
int getBpp() const;
|
||||
//! @brief Get the index of the current palette used
|
||||
int getPaletteIndex() const;
|
||||
//! @brief Get the color pixel reference from the tile address and pixelIndex
|
||||
//! @param tileAddress The starting address of the tile
|
||||
//! @param pixelIndex The index of the pixel (0 - 255)
|
||||
//! @return The color reference
|
||||
//! @note This function is wrapper of getPixelReferenceFromTileRow
|
||||
uint8_t getPixelReferenceFromTile(uint16_t tileAddress, uint8_t pixelIndex);
|
||||
//! @brief Get the color reference of a pixel from the address of the row
|
||||
//! @param tileRowAddress The address of the line of pixel
|
||||
//! @param pixelIndex The index of the pixel (0 - 7)
|
||||
//! @return The color Reference
|
||||
uint8_t getPixelReferenceFromTileRow(uint16_t tileRowAddress, uint8_t pixelIndex);
|
||||
//! @brief Gives the actual selected palette with all of it's colors
|
||||
//! @return The array of color of the palette
|
||||
//! @warning Values are CGRAM colors use PPU::getRealColor function to get the actual real color
|
||||
std::vector<uint16_t> getPalette(int nbPalette);
|
||||
//! @brief read the 2bpp value for a pixel (used multple times for 4bpp and 8bpp)
|
||||
uint8_t read2BPPValue(uint16_t tileRowAddress, uint8_t pixelIndex);
|
||||
//! @brief render the tile (8x8) at the tileAddress
|
||||
//! @param tileAddress The address of the tile to render
|
||||
void render(uint16_t tileAddress);
|
||||
TileRenderer();
|
||||
TileRenderer(const TileRenderer &) = default;
|
||||
~TileRenderer() = default;
|
||||
TileRenderer &operator=(const TileRenderer &) = default;
|
||||
};
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <QIcon>
|
||||
#include <QMenuBar>
|
||||
#include <iostream>
|
||||
#include "SNES.hpp"
|
||||
#include "../../Exceptions/DebuggableError.hpp"
|
||||
#include "QtSFML.hpp"
|
||||
|
||||
@@ -17,67 +18,14 @@
|
||||
|
||||
namespace ComSquare::Renderer
|
||||
{
|
||||
QtSFML::QtSFML(unsigned int h, unsigned int w) :
|
||||
_window(), _sfWidget(nullptr)
|
||||
QtSFML::QtSFML(QWidget *parentWidget)
|
||||
: _window(parentWidget), _sfWidget(nullptr)
|
||||
{
|
||||
this->_window.resize(w, h);
|
||||
this->_window.setWindowIcon(QIcon(":/resources/Logo.png"));
|
||||
}
|
||||
|
||||
void QtSFML::createWindow(SNES &snes, int maxFPS)
|
||||
{
|
||||
this->setWindowName(snes.cartridge->header.gameName);
|
||||
this->_sfWidget = std::make_unique<QtFullSFML>(snes, &_window, QPoint(0, 0), QSize(this->_window.width(), this->_window.height()), maxFPS);
|
||||
this->_window.setCentralWidget(this->_sfWidget.get());
|
||||
|
||||
QMenu *file = this->_window.menuBar()->addMenu("&File");
|
||||
//TODO implement rom opening from this menu.
|
||||
(void)file;
|
||||
|
||||
QMenu *game = this->_window.menuBar()->addMenu("&Game");
|
||||
QAction *reset = new QAction("Reset", &this->_window);
|
||||
QMainWindow::connect(reset, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::reset);
|
||||
game->addAction(reset);
|
||||
|
||||
|
||||
|
||||
QMenu *debugger = this->_window.menuBar()->addMenu("&Debugger");
|
||||
QAction *cpuDebugger = new QAction("CPU's Debugger", &this->_window);
|
||||
cpuDebugger->setShortcut(Qt::Key_F1);
|
||||
QMainWindow::connect(cpuDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugCPU);
|
||||
debugger->addAction(cpuDebugger);
|
||||
|
||||
QAction *ramViewer = new QAction("Memory viewer", &this->_window);
|
||||
ramViewer->setShortcut(Qt::Key_F2);
|
||||
QMainWindow::connect(ramViewer, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableRamViewer);
|
||||
debugger->addAction(ramViewer);
|
||||
|
||||
QAction *headerViewer = new QAction("Header viewer", &this->_window);
|
||||
headerViewer->setShortcut(Qt::Key_F3);
|
||||
QMainWindow::connect(headerViewer, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableHeaderViewer);
|
||||
debugger->addAction(headerViewer);
|
||||
|
||||
QAction *apuDebugger = new QAction("APU's Debugger", &this->_window);
|
||||
apuDebugger->setShortcut(Qt::Key_F4);
|
||||
QMainWindow::connect(apuDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugAPU);
|
||||
debugger->addAction(apuDebugger);
|
||||
|
||||
QAction *busDebugger = new QAction("Memory bus Viewer", &this->_window);
|
||||
busDebugger->setShortcut(Qt::Key_F5);
|
||||
QMainWindow::connect(busDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugBus);
|
||||
debugger->addAction(busDebugger);
|
||||
|
||||
QAction *cgramDebugger = new QAction("Palette Viewer", &this->_window);
|
||||
cgramDebugger->setShortcut(Qt::Key_F6);
|
||||
QMainWindow::connect(cgramDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableCgramViewer);
|
||||
debugger->addAction(cgramDebugger);
|
||||
|
||||
QAction *registerDebugger = new QAction("Registers Viewer", &this->_window);
|
||||
registerDebugger->setShortcut(Qt::Key_F7);
|
||||
QMainWindow::connect(registerDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableRegisterViewer);
|
||||
debugger->addAction(registerDebugger);
|
||||
|
||||
this->_window.show();
|
||||
this->_sfWidget = std::make_unique<QtFullSFML>(snes, this->_window, QPoint(0, 0), QSize(this->_window->width(), this->_window->height()), maxFPS);
|
||||
}
|
||||
|
||||
void QtSFML::putPixel(unsigned y, unsigned x, uint32_t rgba)
|
||||
@@ -94,7 +42,7 @@ namespace ComSquare::Renderer
|
||||
|
||||
void QtSFML::setWindowName(std::string &newWindowName)
|
||||
{
|
||||
this->_window.setWindowTitle((newWindowName + " - ComSquare").c_str());
|
||||
this->_window->setWindowTitle((newWindowName + " - ComSquare").c_str());
|
||||
}
|
||||
|
||||
QtFullSFML::QtFullSFML(SNES &snes, QWidget *parent, const QPoint &position, const QSize &size, int frameRate) :
|
||||
@@ -154,4 +102,77 @@ namespace ComSquare::Renderer
|
||||
{
|
||||
this->_snes.enableRegisterDebugging();
|
||||
}
|
||||
|
||||
void QtFullSFML::enableTileViewer()
|
||||
{
|
||||
this->_snes.enableTileViewerDebugging();
|
||||
}
|
||||
|
||||
QtSFMLWindow::QtSFMLWindow(unsigned int height, unsigned int width)
|
||||
: QtSFML(&this->_window)
|
||||
{
|
||||
this->_window.resize(width, height);
|
||||
this->_window.setWindowIcon(QIcon(":/resources/Logo.png"));
|
||||
}
|
||||
|
||||
void QtSFMLWindow::createWindow(SNES &snes, int maxFPS)
|
||||
{
|
||||
QtSFML::createWindow(snes, maxFPS);
|
||||
this->setWindowName(snes.cartridge->header.gameName);
|
||||
this->_window.setCentralWidget(this->_sfWidget.get());
|
||||
|
||||
QMenu *file = this->_window.menuBar()->addMenu("&File");
|
||||
//TODO implement rom opening from this menu.
|
||||
(void)file;
|
||||
|
||||
QMenu *game = this->_window.menuBar()->addMenu("&Game");
|
||||
QAction *reset = new QAction("Reset", &this->_window);
|
||||
QMainWindow::connect(reset, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::reset);
|
||||
game->addAction(reset);
|
||||
|
||||
|
||||
|
||||
QMenu *debugger = this->_window.menuBar()->addMenu("&Debugger");
|
||||
QAction *cpuDebugger = new QAction("CPU's Debugger", &this->_window);
|
||||
cpuDebugger->setShortcut(Qt::Key_F1);
|
||||
QMainWindow::connect(cpuDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugCPU);
|
||||
debugger->addAction(cpuDebugger);
|
||||
|
||||
QAction *ramViewer = new QAction("Memory viewer", &this->_window);
|
||||
ramViewer->setShortcut(Qt::Key_F2);
|
||||
QMainWindow::connect(ramViewer, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableRamViewer);
|
||||
debugger->addAction(ramViewer);
|
||||
|
||||
QAction *headerViewer = new QAction("Header viewer", &this->_window);
|
||||
headerViewer->setShortcut(Qt::Key_F3);
|
||||
QMainWindow::connect(headerViewer, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableHeaderViewer);
|
||||
debugger->addAction(headerViewer);
|
||||
|
||||
QAction *apuDebugger = new QAction("APU's Debugger", &this->_window);
|
||||
apuDebugger->setShortcut(Qt::Key_F4);
|
||||
QMainWindow::connect(apuDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugAPU);
|
||||
debugger->addAction(apuDebugger);
|
||||
|
||||
QAction *busDebugger = new QAction("Memory bus Viewer", &this->_window);
|
||||
busDebugger->setShortcut(Qt::Key_F5);
|
||||
QMainWindow::connect(busDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugBus);
|
||||
debugger->addAction(busDebugger);
|
||||
|
||||
QAction *cgramDebugger = new QAction("Palette Viewer", &this->_window);
|
||||
cgramDebugger->setShortcut(Qt::Key_F6);
|
||||
QMainWindow::connect(cgramDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableCgramViewer);
|
||||
debugger->addAction(cgramDebugger);
|
||||
|
||||
QAction *registerDebugger = new QAction("Registers Viewer", &this->_window);
|
||||
registerDebugger->setShortcut(Qt::Key_F7);
|
||||
QMainWindow::connect(registerDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableRegisterViewer);
|
||||
debugger->addAction(registerDebugger);
|
||||
|
||||
QAction *tileDebugger = new QAction("Tile Viewer", &this->_window);
|
||||
tileDebugger->setShortcut(Qt::Key_F8);
|
||||
QMainWindow::connect(tileDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableTileViewer);
|
||||
debugger->addAction(tileDebugger);
|
||||
|
||||
this->_window.show();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,8 @@ namespace ComSquare::Renderer
|
||||
void enableCgramViewer();
|
||||
//! @brief Action called when clicking on the enable DMA viewer button.
|
||||
void enableRegisterViewer();
|
||||
//! @brief Action called when clicking on the enable Tile viewer button
|
||||
void enableTileViewer();
|
||||
|
||||
//! @brief Action called when clicking on the reset button.
|
||||
void reset();
|
||||
@@ -44,20 +46,21 @@ namespace ComSquare::Renderer
|
||||
QtFullSFML(SNES &snes, QWidget* parent, const QPoint& position, const QSize& size, int frameRate = 0);
|
||||
QtFullSFML(const QtFullSFML &) = delete;
|
||||
QtFullSFML &operator=(const QtFullSFML &) = delete;
|
||||
~QtFullSFML() override = default;
|
||||
~QtFullSFML() = default;
|
||||
};
|
||||
|
||||
//! @brief A SFML renderer inside a QT window.
|
||||
//! @brief A SFML renderer inside a QT widget.
|
||||
class QtSFML : public IRenderer {
|
||||
private:
|
||||
//! @brief The main window that the app reside on.
|
||||
QMainWindow _window;
|
||||
QWidget *_window;
|
||||
protected:
|
||||
//! @brief The SFML widget.
|
||||
std::unique_ptr<QtFullSFML> _sfWidget = nullptr;
|
||||
public:
|
||||
//! @brief Use this function to create the window.
|
||||
//! @param maxFPS The number of FPS you aim to run on.
|
||||
void createWindow(SNES &snes, int maxFPS) override;
|
||||
virtual void createWindow(SNES &snes, int maxFPS) override;
|
||||
//! @brief Add a pixel to the buffer to the coordinates x, y with the color rgba.
|
||||
//! @param X horizontal index.
|
||||
//! @param Y vertical index.
|
||||
@@ -72,14 +75,29 @@ namespace ComSquare::Renderer
|
||||
//! @brief Set a new name to the window, if there is already a name it will be overwrite.
|
||||
//! @param newWindowName new title for the window.
|
||||
void setWindowName(std::string &newWindowName) override;
|
||||
//! @brief Constructor that return a SFML renderer inside a QT window.
|
||||
//! @param height _height of the window.
|
||||
//! @param width _width of the window.
|
||||
QtSFML(unsigned int height, unsigned int width);
|
||||
//! @brief Constructor that return a SFML renderer inside a QT widget.
|
||||
QtSFML(QWidget *parentWidget);
|
||||
QtSFML(const QtSFML &) = delete;
|
||||
QtSFML &operator=(const QtSFML &) = delete;
|
||||
~QtSFML() = default;
|
||||
};
|
||||
|
||||
class QtSFMLWindow : public QtSFML {
|
||||
private:
|
||||
//! @brief The main window that the app reside on.
|
||||
QMainWindow _window;
|
||||
public:
|
||||
//! @brief Use this function to create the window.
|
||||
//! @param maxFPS The number of FPS you aim to run on.
|
||||
void createWindow(SNES &snes, int maxFPS) override;
|
||||
//! @brief Constructor that return a SFML renderer inside a QT window.
|
||||
//! @param height _height of the window.
|
||||
//! @param width _width of the window.
|
||||
QtSFMLWindow(unsigned int height, unsigned int width);
|
||||
QtSFMLWindow(const QtSFMLWindow &) = delete;
|
||||
QtSFMLWindow &operator=(const QtSFMLWindow &) = delete;
|
||||
~QtSFMLWindow() = default;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //COMSQUARE_QTSFML_HPP
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by cbihan on 08/06/2021.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "QtSfmlTileRenderer.hpp"
|
||||
|
||||
namespace ComSquare::Renderer
|
||||
{
|
||||
|
||||
QtSFMLTileRenderer::QtSFMLTileRenderer(QWidget *parent,
|
||||
int frameRate)
|
||||
: QtWidgetSFML(parent, {0, 0}, {1025, 1025}, frameRate)
|
||||
{
|
||||
// todo the size of the sfml renderwindow should fill the parent
|
||||
}
|
||||
|
||||
void QtSFMLTileRenderer::_onUpdate()
|
||||
{
|
||||
this->_window.clear(sf::Color::Black);
|
||||
for (unsigned long i = 0; i < this->buffer.size(); i++) {
|
||||
for (unsigned long j = 0; j < this->buffer[i].size(); j++) {
|
||||
this->putPixel(j, i, this->buffer[i][j]);
|
||||
}
|
||||
}
|
||||
this->drawScreen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Created by cbihan on 08/06/2021.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include "QtWidgetSFML.hpp"
|
||||
#include "Debugger/TileViewer/RAMTileRenderer.hpp"
|
||||
|
||||
namespace ComSquare::Renderer
|
||||
{
|
||||
class QtSFMLTileRenderer : public QtWidgetSFML
|
||||
{
|
||||
public:
|
||||
std::array<std::array<uint32_t, 1024>, 1024> buffer;
|
||||
|
||||
//! @brief Function called to update this widget.
|
||||
void _onUpdate() override;
|
||||
|
||||
//! @brief ctor
|
||||
explicit QtSFMLTileRenderer(QWidget* parent, int frameRate = 0);
|
||||
//! @brief copy ctor
|
||||
QtSFMLTileRenderer(const QtSFMLTileRenderer &) = delete;
|
||||
//! @brief default ctor
|
||||
~QtSFMLTileRenderer() override = default;
|
||||
//! @brief assignment operator
|
||||
QtSFMLTileRenderer &operator=(const QtSFMLTileRenderer &) = delete;
|
||||
};
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace ComSquare::Renderer
|
||||
//! @brief QT event that refresh the widget. (A draw screen)
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
// @brief Internal timer used for update intervals.
|
||||
//! @brief Internal timer used for update intervals.
|
||||
QTimer _timer;
|
||||
//! @brief Has the SF window been created yet.
|
||||
bool _isInitialized = false;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <SFML/System.hpp>
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include "SNES.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace ComSquare::Renderer
|
||||
@@ -67,11 +68,7 @@ namespace ComSquare::Renderer
|
||||
if (y >= this->_videoMode.height)
|
||||
throw InvalidPixelPosition("Height", y, this->_videoMode.height);
|
||||
|
||||
sf::Color pixels;
|
||||
pixels.r = rgba >> 24U;
|
||||
pixels.g = rgba >> 16U;
|
||||
pixels.b = rgba >> 8U;
|
||||
pixels.a = rgba >> 0U;
|
||||
sf::Color pixels(rgba);
|
||||
this->_pixelBuffer[this->_videoMode.width * y + x] = pixels;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#define COMSQUARE_SFRENDERER_HPP
|
||||
|
||||
#include "IRenderer.hpp"
|
||||
#include "../SNES.hpp"
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/System.hpp>
|
||||
|
||||
+22
-4
@@ -10,6 +10,7 @@
|
||||
#include "Debugger/APUDebug.hpp"
|
||||
#include "Debugger/MemoryBusDebug.hpp"
|
||||
#include "Debugger/CGramDebug.hpp"
|
||||
#include "Debugger/TileViewer/TileViewer.hpp"
|
||||
#endif
|
||||
|
||||
namespace ComSquare
|
||||
@@ -124,7 +125,7 @@ namespace ComSquare
|
||||
|
||||
void SNES::enableMemoryBusDebugging()
|
||||
{
|
||||
#ifdef DEBUGGER_ENABLED
|
||||
#ifdef DEBUGGER_ENABLED
|
||||
if (this->bus->isDebugger())
|
||||
std::static_pointer_cast<Debugger::MemoryBusDebug>(this->bus)->focus();
|
||||
else
|
||||
@@ -132,9 +133,9 @@ namespace ComSquare
|
||||
this->bus = std::make_shared<Debugger::MemoryBusDebug>(*this, *this->bus);
|
||||
this->cpu->setMemoryBus(this->bus);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SNES::disableMemoryBusDebugging()
|
||||
@@ -160,7 +161,7 @@ namespace ComSquare
|
||||
void SNES::disableCgramDebugging()
|
||||
{
|
||||
#ifdef DEBUGGER_ENABLED
|
||||
this->_cgramViewer = nullptr;
|
||||
this->_cgramViewer = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -180,4 +181,21 @@ namespace ComSquare
|
||||
this->_registerViewer = std::make_unique<Debugger::RegisterViewer>(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SNES::disableTileViewerDebugging()
|
||||
{
|
||||
#ifdef DEBUGGER_ENABLED
|
||||
this->_tileViewer = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SNES::enableTileViewerDebugging()
|
||||
{
|
||||
#ifdef DEBUGGER_ENABLED
|
||||
if (this->_tileViewer)
|
||||
this->_tileViewer->focus();
|
||||
else
|
||||
this->_tileViewer = std::make_unique<Debugger::TileViewer>(*this, *this->ppu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Debugger/HeaderViewer.hpp"
|
||||
#include "Debugger/CGramDebug.hpp"
|
||||
#include "Debugger/RegisterViewer.hpp"
|
||||
#include "Debugger/TileViewer/TileViewer.hpp"
|
||||
#endif
|
||||
|
||||
namespace ComSquare
|
||||
@@ -35,6 +36,8 @@ namespace ComSquare
|
||||
std::unique_ptr<Debugger::CGramDebug> _cgramViewer;
|
||||
//! @brief The window that allow the user to view registers.
|
||||
std::unique_ptr<Debugger::RegisterViewer> _registerViewer;
|
||||
//! @brief The window that allow the user to view the cgram as tiles.
|
||||
std::unique_ptr<Debugger::TileViewer> _tileViewer;
|
||||
#endif
|
||||
public:
|
||||
//! @brief The memory bus that map addresses to components.
|
||||
@@ -87,6 +90,10 @@ namespace ComSquare
|
||||
void disableRegisterDebugging();
|
||||
//! @brief Enable the Register's debugging window.
|
||||
void enableRegisterDebugging();
|
||||
//! @brief Disable the TileViewer's debugging window.
|
||||
void disableTileViewerDebugging();
|
||||
//! @brief Enable the TileViewer's debugging window.
|
||||
void enableTileViewerDebugging();
|
||||
|
||||
//! @brief Create all the components using a common memory bus for all of them.
|
||||
SNES(const std::string &ramPath, Renderer::IRenderer &renderer);
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <getopt.h>
|
||||
#include "SNES.hpp"
|
||||
#include "Renderer/SFRenderer.hpp"
|
||||
#include "Renderer/QtRenderer/QtSFML.hpp"
|
||||
|
||||
using namespace ComSquare;
|
||||
@@ -81,7 +80,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
QApplication app(argc, argv);
|
||||
QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
||||
Renderer::QtSFML renderer(1100, 1100);
|
||||
Renderer::QtSFMLWindow renderer(1100, 1100);
|
||||
try {
|
||||
SNES snes(argv[1], renderer);
|
||||
renderer.createWindow(snes, 60);
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TileViewer</class>
|
||||
<widget class="QMainWindow" name="TileViewer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>577</width>
|
||||
<height>478</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tile Viewer</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../resources/appResources.qrc">
|
||||
<normaloff>:/resources/Logo.png</normaloff>:/resources/Logo.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_sfml" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="Address">
|
||||
<property name="prefix">
|
||||
<string notr="true">0x</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>4096</number>
|
||||
</property>
|
||||
<property name="stepType">
|
||||
<enum>QAbstractSpinBox::DefaultStepType</enum>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>SIze (bytes)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="ByteSize">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string notr="true">0x</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>4096</number>
|
||||
</property>
|
||||
<property name="stepType">
|
||||
<enum>QAbstractSpinBox::DefaultStepType</enum>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20480</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="BppFormat">
|
||||
<property name="currentText">
|
||||
<string>2 bpp</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>hjhu</string>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2 bpp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4 bpp</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8 bpp</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="cursor">
|
||||
<cursorShape>ArrowCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Columns</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring></cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="NbColumns">
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Palette Index</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="PaletteIndex">
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>577</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../resources/appResources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user