mirror of https://github.com/stella-emu/stella.git
The TIA image in the debugger is now correctly rendered in greyscale
below the current electron beam position. Fix long-standing bug whereby entering the debugger for the first time and tracing/scanline advancing, the TIA image was blanked, and didn't work correctly until you exited and re-entered the debugger. Minor refactoring optimizations, and renaming of methods.
This commit is contained in:
parent
39f756f821
commit
c99cb33cda
|
@ -111,7 +111,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
|
||||||
{
|
{
|
||||||
ostringstream command;
|
ostringstream command;
|
||||||
int lines = myClickY + ystart;
|
int lines = myClickY + ystart;
|
||||||
if(instance().console().tia().partialFrame())
|
if(instance().console().tia().isRendering())
|
||||||
lines -= instance().console().tia().scanlines();
|
lines -= instance().console().tia().scanlines();
|
||||||
if(lines > 0)
|
if(lines > 0)
|
||||||
{
|
{
|
||||||
|
@ -156,7 +156,7 @@ void TiaOutputWidget::drawWidget(bool hilite)
|
||||||
// This determines where the frame greying should start, and where a
|
// This determines where the frame greying should start, and where a
|
||||||
// scanline 'pointer' should be drawn
|
// scanline 'pointer' should be drawn
|
||||||
uInt16 scanx, scany, scanoffset;
|
uInt16 scanx, scany, scanoffset;
|
||||||
bool visible = instance().console().tia().scanlinePos(scanx, scany);
|
bool visible = instance().console().tia().electronBeamPos(scanx, scany);
|
||||||
scanoffset = width * scany + scanx;
|
scanoffset = width * scany + scanx;
|
||||||
|
|
||||||
for(uInt32 y = 0, i = 0; y < height; ++y)
|
for(uInt32 y = 0, i = 0; y < height; ++y)
|
||||||
|
@ -164,7 +164,7 @@ void TiaOutputWidget::drawWidget(bool hilite)
|
||||||
uInt32* line_ptr = myLineBuffer;
|
uInt32* line_ptr = myLineBuffer;
|
||||||
for(uInt32 x = 0; x < width; ++x, ++i)
|
for(uInt32 x = 0; x < width; ++x, ++i)
|
||||||
{
|
{
|
||||||
uInt8 shift = i > scanoffset ? 1 : 0;
|
uInt8 shift = i >= scanoffset ? 1 : 0;
|
||||||
uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift);
|
uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift);
|
||||||
*line_ptr++ = pixel;
|
*line_ptr++ = pixel;
|
||||||
*line_ptr++ = pixel;
|
*line_ptr++ = pixel;
|
||||||
|
|
|
@ -254,7 +254,7 @@ void TiaZoomWidget::drawWidget(bool hilite)
|
||||||
// Get current scanline position
|
// Get current scanline position
|
||||||
// This determines where the frame greying should start
|
// This determines where the frame greying should start
|
||||||
uInt16 scanx, scany, scanoffset;
|
uInt16 scanx, scany, scanoffset;
|
||||||
instance().console().tia().scanlinePos(scanx, scany);
|
instance().console().tia().electronBeamPos(scanx, scany);
|
||||||
scanoffset = width * scany + scanx;
|
scanoffset = width * scany + scanx;
|
||||||
|
|
||||||
int x, y, col, row;
|
int x, y, col, row;
|
||||||
|
|
|
@ -405,8 +405,6 @@ void Console::setProperties(const Properties& props)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBInitStatus Console::initializeVideo(bool full)
|
FBInitStatus Console::initializeVideo(bool full)
|
||||||
{
|
{
|
||||||
setPalette(myOSystem.settings().getString("palette"));
|
|
||||||
|
|
||||||
FBInitStatus fbstatus = kSuccess;
|
FBInitStatus fbstatus = kSuccess;
|
||||||
|
|
||||||
if(full)
|
if(full)
|
||||||
|
@ -421,6 +419,7 @@ FBInitStatus Console::initializeVideo(bool full)
|
||||||
myOSystem.frameBuffer().showFrameStats(myOSystem.settings().getBool("stats"));
|
myOSystem.frameBuffer().showFrameStats(myOSystem.settings().getBool("stats"));
|
||||||
generateColorLossPalette();
|
generateColorLossPalette();
|
||||||
}
|
}
|
||||||
|
setPalette(myOSystem.settings().getString("palette"));
|
||||||
|
|
||||||
// Set the correct framerate based on the format of the ROM
|
// Set the correct framerate based on the format of the ROM
|
||||||
// This can be overridden by changing the framerate in the
|
// This can be overridden by changing the framerate in the
|
||||||
|
|
|
@ -274,7 +274,7 @@ void FrameBuffer::update()
|
||||||
const ConsoleInfo& info = myOSystem.console().about();
|
const ConsoleInfo& info = myOSystem.console().about();
|
||||||
char msg[30];
|
char msg[30];
|
||||||
std::snprintf(msg, 30, "%3u @ %3.2ffps => %s",
|
std::snprintf(msg, 30, "%3u @ %3.2ffps => %s",
|
||||||
myOSystem.console().tia().scanlines(),
|
myOSystem.console().tia().scanlinesLastFrame(),
|
||||||
myOSystem.console().getFramerate(), info.DisplayFormat.c_str());
|
myOSystem.console().getFramerate(), info.DisplayFormat.c_str());
|
||||||
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
|
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
|
||||||
myStatsMsg.surface->drawString(infoFont(),
|
myStatsMsg.surface->drawString(infoFont(),
|
||||||
|
|
|
@ -230,7 +230,7 @@ void FrameManager::updateAutodetectedTvMode()
|
||||||
updateTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
|
updateTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
|
||||||
else if (!myModeConfirmed) {
|
else if (!myModeConfirmed) {
|
||||||
if (
|
if (
|
||||||
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
||||||
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
||||||
(myCurrentFrameFinalLines % 2)
|
(myCurrentFrameFinalLines % 2)
|
||||||
)
|
)
|
||||||
|
@ -289,7 +289,8 @@ void FrameManager::setYstart(uInt32 ystart)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 FrameManager::ystart() const {
|
uInt32 FrameManager::ystart() const
|
||||||
|
{
|
||||||
return myVblankManager.ystart();
|
return myVblankManager.ystart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +330,12 @@ uInt32 FrameManager::scanlines() const
|
||||||
return myCurrentFrameTotalLines;
|
return myCurrentFrameTotalLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 FrameManager::scanlinesLastFrame() const
|
||||||
|
{
|
||||||
|
return myCurrentFrameFinalLines;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::setTvMode(TvMode mode)
|
void FrameManager::setTvMode(TvMode mode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,13 +61,12 @@ class FrameManager : public Serializable
|
||||||
|
|
||||||
void setFixedHeight(uInt32 height);
|
void setFixedHeight(uInt32 height);
|
||||||
|
|
||||||
uInt32 getY() const
|
uInt32 getY() const { return myY; }
|
||||||
{
|
|
||||||
return myY;
|
|
||||||
}
|
|
||||||
|
|
||||||
uInt32 scanlines() const;
|
uInt32 scanlines() const;
|
||||||
|
|
||||||
|
uInt32 scanlinesLastFrame() const;
|
||||||
|
|
||||||
uInt32 frameCount() const { return myTotalFrames; }
|
uInt32 frameCount() const { return myTotalFrames; }
|
||||||
|
|
||||||
float frameRate() const { return myFrameRate; }
|
float frameRate() const { return myFrameRate; }
|
||||||
|
|
|
@ -199,12 +199,13 @@ bool TIA::save(Serializer& out) const
|
||||||
// TODO - save instance variables
|
// TODO - save instance variables
|
||||||
|
|
||||||
// Save the state of each graphics object
|
// Save the state of each graphics object
|
||||||
if(!myPlayfield.save(out)) return false;
|
if(!myBackground.save(out)) return false;
|
||||||
if(!myMissile0.save(out)) return false;
|
if(!myPlayfield.save(out)) return false;
|
||||||
if(!myMissile1.save(out)) return false;
|
if(!myMissile0.save(out)) return false;
|
||||||
if(!myPlayer0.save(out)) return false;
|
if(!myMissile1.save(out)) return false;
|
||||||
if(!myPlayer1.save(out)) return false;
|
if(!myPlayer0.save(out)) return false;
|
||||||
if(!myBall.save(out)) return false;
|
if(!myPlayer1.save(out)) return false;
|
||||||
|
if(!myBall.save(out)) return false;
|
||||||
|
|
||||||
// Save the sound sample stuff ...
|
// Save the sound sample stuff ...
|
||||||
mySound.save(out);
|
mySound.save(out);
|
||||||
|
@ -229,12 +230,13 @@ bool TIA::load(Serializer& in)
|
||||||
// TODO - load instance variables
|
// TODO - load instance variables
|
||||||
|
|
||||||
// Load the state of each graphics object
|
// Load the state of each graphics object
|
||||||
if(!myPlayfield.load(in)) return false;
|
if(!myBackground.load(in)) return false;
|
||||||
if(!myMissile0.load(in)) return false;
|
if(!myPlayfield.load(in)) return false;
|
||||||
if(!myMissile1.load(in)) return false;
|
if(!myMissile0.load(in)) return false;
|
||||||
if(!myPlayer0.load(in)) return false;
|
if(!myMissile1.load(in)) return false;
|
||||||
if(!myPlayer1.load(in)) return false;
|
if(!myPlayer0.load(in)) return false;
|
||||||
if(!myBall.load(in)) return false;
|
if(!myPlayer1.load(in)) return false;
|
||||||
|
if(!myBall.load(in)) return false;
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -344,6 +346,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
// It appears that the 6507 only halts during a read cycle so
|
// It appears that the 6507 only halts during a read cycle so
|
||||||
// we test here for follow-on writes which should be ignored as
|
// we test here for follow-on writes which should be ignored as
|
||||||
// far as halting the processor is concerned.
|
// far as halting the processor is concerned.
|
||||||
|
// See issue #42 for more information.
|
||||||
if (mySystem->m6502().lastAccessWasRead())
|
if (mySystem->m6502().lastAccessWasRead())
|
||||||
{
|
{
|
||||||
mySubClock += (228 - myHctr) % 228;
|
mySubClock += (228 - myHctr) % 228;
|
||||||
|
@ -614,54 +617,6 @@ void TIA::update()
|
||||||
mySystem->m6502().execute(25000);
|
mySystem->m6502().execute(25000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 TIA::height() const
|
|
||||||
{
|
|
||||||
return myFrameManager.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 TIA::ystart() const
|
|
||||||
{
|
|
||||||
return myFrameManager.ystart();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIA::setHeight(uInt32 height)
|
|
||||||
{
|
|
||||||
myFrameManager.setFixedHeight(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIA::setYStart(uInt32 ystart)
|
|
||||||
{
|
|
||||||
myFrameManager.setYstart(ystart);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIA::autodetectTvMode(bool toggle)
|
|
||||||
{
|
|
||||||
myFrameManager.autodetectTvMode(toggle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIA::setTvMode(TvMode mode)
|
|
||||||
{
|
|
||||||
myFrameManager.setTvMode(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
TvMode TIA::tvMode() const
|
|
||||||
{
|
|
||||||
return myFrameManager.tvMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIA::enableAutoFrame(bool enabled)
|
|
||||||
{
|
|
||||||
myAutoFrameEnabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// TODO: stub
|
// TODO: stub
|
||||||
void TIA::enableColorLoss(bool enabled)
|
void TIA::enableColorLoss(bool enabled)
|
||||||
|
@ -669,48 +624,12 @@ void TIA::enableColorLoss(bool enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 TIA::clocksThisLine() const
|
bool TIA::electronBeamPos(uInt16& x, uInt16& y) const
|
||||||
{
|
{
|
||||||
return myHctr + myXDelta;
|
x = clocksThisLine();
|
||||||
}
|
y = myFrameManager.getY();
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
return isRendering();
|
||||||
uInt32 TIA::scanlines() const
|
|
||||||
{
|
|
||||||
return myFrameManager.scanlines();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool TIA::partialFrame() const
|
|
||||||
{
|
|
||||||
return myFrameManager.isRendering();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool TIA::scanlinePos(uInt16& x, uInt16& y) const
|
|
||||||
{
|
|
||||||
if(partialFrame())
|
|
||||||
{
|
|
||||||
// We only care about the scanline position when it's in the viewable area
|
|
||||||
if(1)//myFramePointerClocks >= myFramePointerOffset)
|
|
||||||
{
|
|
||||||
x = clocksThisLine();//(myFramePointerClocks - myFramePointerOffset) % 160;
|
|
||||||
y = myFrameManager.getY();//(myFramePointerClocks - myFramePointerOffset) / 160;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = width();
|
|
||||||
y = height();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -850,12 +769,8 @@ void TIA::updateScanline()
|
||||||
{
|
{
|
||||||
// Update frame by one scanline at a time
|
// Update frame by one scanline at a time
|
||||||
uInt32 line = scanlines();
|
uInt32 line = scanlines();
|
||||||
cerr << "-> " << line << endl;
|
|
||||||
while (line == scanlines())
|
while (line == scanlines())
|
||||||
{
|
|
||||||
updateScanlineByStep();
|
updateScanlineByStep();
|
||||||
cerr << line << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -151,31 +151,27 @@ class TIA : public Device
|
||||||
/**
|
/**
|
||||||
Answers the current and previous frame buffer pointers
|
Answers the current and previous frame buffer pointers
|
||||||
*/
|
*/
|
||||||
uInt8* currentFrameBuffer() const {
|
uInt8* currentFrameBuffer() const { return myCurrentFrameBuffer.get(); }
|
||||||
return myCurrentFrameBuffer.get();
|
uInt8* previousFrameBuffer() const { return myPreviousFrameBuffer.get(); }
|
||||||
}
|
|
||||||
uInt8* previousFrameBuffer() const {
|
|
||||||
return myPreviousFrameBuffer.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers dimensional info about the framebuffer
|
Answers dimensional info about the framebuffer
|
||||||
*/
|
*/
|
||||||
uInt32 width() const { return 160; }
|
uInt32 width() const { return 160; }
|
||||||
uInt32 height() const;
|
uInt32 height() const { return myFrameManager.height(); }
|
||||||
uInt32 ystart() const;
|
uInt32 ystart() const { return myFrameManager.ystart(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Changes the current Height/YStart properties.
|
Changes the current Height/YStart properties.
|
||||||
Note that calls to these method(s) must be eventually followed by
|
Note that calls to these method(s) must be eventually followed by
|
||||||
::frameReset() for the changes to take effect.
|
::frameReset() for the changes to take effect.
|
||||||
*/
|
*/
|
||||||
void setHeight(uInt32 height);
|
void setHeight(uInt32 height) { myFrameManager.setFixedHeight(height); }
|
||||||
void setYStart(uInt32 ystart);
|
void setYStart(uInt32 ystart) { myFrameManager.setYstart(ystart); }
|
||||||
|
|
||||||
void autodetectTvMode(bool toggle);
|
void autodetectTvMode(bool toggle) { myFrameManager.autodetectTvMode(toggle); }
|
||||||
void setTvMode(TvMode mode);
|
void setTvMode(TvMode mode) { myFrameManager.setTvMode(mode); }
|
||||||
TvMode tvMode() const;
|
TvMode tvMode() const { return myFrameManager.tvMode(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enables/disables auto-frame calculation. If enabled, the TIA
|
Enables/disables auto-frame calculation. If enabled, the TIA
|
||||||
|
@ -183,7 +179,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@param enabled Whether to enable or disable all auto-frame calculation
|
@param enabled Whether to enable or disable all auto-frame calculation
|
||||||
*/
|
*/
|
||||||
void enableAutoFrame(bool enabled);
|
void enableAutoFrame(bool enabled) { myAutoFrameEnabled = enabled; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enables/disables color-loss for PAL modes only.
|
Enables/disables color-loss for PAL modes only.
|
||||||
|
@ -197,7 +193,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return The current color clock
|
@return The current color clock
|
||||||
*/
|
*/
|
||||||
uInt32 clocksThisLine() const;
|
uInt32 clocksThisLine() const { return myHctr + myXDelta; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the total number of scanlines the TIA generated in producing
|
Answers the total number of scanlines the TIA generated in producing
|
||||||
|
@ -206,27 +202,32 @@ class TIA : public Device
|
||||||
|
|
||||||
@return The total number of scanlines generated
|
@return The total number of scanlines generated
|
||||||
*/
|
*/
|
||||||
uInt32 scanlines() const;
|
uInt32 scanlines() const { return myFrameManager.scanlines(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers whether the TIA is currently in 'partial frame' mode
|
Answers the total number of scanlines the TIA generated in the
|
||||||
|
previous frame.
|
||||||
|
|
||||||
|
@return The total number of scanlines generated in the last frame.
|
||||||
|
*/
|
||||||
|
uInt32 scanlinesLastFrame() const { return myFrameManager.scanlinesLastFrame(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Answers whether the TIA is currently in being rendered
|
||||||
(we're in between the start and end of drawing a frame).
|
(we're in between the start and end of drawing a frame).
|
||||||
|
|
||||||
@return If we're in partial frame mode
|
@return If the frame is in rendering mode
|
||||||
*/
|
*/
|
||||||
bool partialFrame() const;
|
bool isRendering() const { return myFrameManager.isRendering(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the current position of the virtual 'electron beam' used to
|
Answers the current position of the virtual 'electron beam' used to
|
||||||
draw the TIA image. If not in partial frame mode, the position is
|
draw the TIA image.
|
||||||
defined to be in the lower right corner (@ width/height of the screen).
|
|
||||||
Note that the coordinates are with respect to currentFrameBuffer(),
|
|
||||||
taking any YStart values into account.
|
|
||||||
|
|
||||||
@return The x/y coordinates of the scanline electron beam, and whether
|
@return The x/y coordinates of the scanline electron beam, and whether
|
||||||
it is in the visible/viewable area of the screen
|
it is in the visible/viewable area of the screen
|
||||||
*/
|
*/
|
||||||
bool scanlinePos(uInt16& x, uInt16& y) const;
|
bool electronBeamPos(uInt16& x, uInt16& y) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enables/disable/toggle the specified (or all) TIA bit(s). Note that
|
Enables/disable/toggle the specified (or all) TIA bit(s). Note that
|
||||||
|
|
Loading…
Reference in New Issue