mirror of
https://github.com/holub/mame
synced 2025-07-07 19:03:29 +03:00
More accurate pixel clocks for Sega Saturn / ST-V [Angelo Salese]
This commit is contained in:
parent
17f02def66
commit
a01fcb25b3
@ -5,7 +5,7 @@
|
||||
Driver by David Haywood, Angelo Salese, Olivier Galibert & Mariusz Wojcieszek
|
||||
SCSP driver provided by R.Belmont, based on ElSemi's SCSP sound chip emulator
|
||||
CD Block driver provided by ANY, based on sthief original emulator
|
||||
Many thanks to Guru, Fabien & Runik for the help given.
|
||||
Many thanks to Guru, Fabien, Runik and Charles MacDonald for the help given.
|
||||
|
||||
===================================================================================================
|
||||
|
||||
@ -119,11 +119,6 @@ also has a DSP;
|
||||
#define LOG_IOGA 0
|
||||
|
||||
|
||||
|
||||
#define MASTER_CLOCK_352 57272800
|
||||
#define MASTER_CLOCK_320 53748200
|
||||
#define PIXEL_CLOCK 50160000/2/4 /*TODO: fix me up! */
|
||||
|
||||
/**************************************************************************************/
|
||||
/*to be added into a stv Header file,remember to remove all the static...*/
|
||||
|
||||
@ -2546,9 +2541,7 @@ SCU register[36] is the timer zero compare register.
|
||||
SCU register[40] is for IRQ masking.
|
||||
*/
|
||||
|
||||
#define NEW_IRQ_CODE 0
|
||||
|
||||
#if NEW_IRQ_CODE
|
||||
static TIMER_DEVICE_CALLBACK( saturn_scanline )
|
||||
{
|
||||
saturn_state *state = timer.machine().driver_data<saturn_state>();
|
||||
@ -2556,21 +2549,18 @@ static TIMER_DEVICE_CALLBACK( saturn_scanline )
|
||||
int max_y = timer.machine().primary_screen->height();
|
||||
int y_step;
|
||||
|
||||
if(max_y == 264)
|
||||
y_step = 1;
|
||||
else
|
||||
y_step = 2;
|
||||
y_step = (max_y == 263) ? 1 : 2;
|
||||
|
||||
popmessage("%08x %d %08x %08x",state->m_scu_regs[40] ^ 0xffffffff,max_y,state->m_scu_regs[36],state->m_scu_regs[38]);
|
||||
//popmessage("%08x %d %08x %08x",state->m_scu_regs[40] ^ 0xffffffff,max_y,state->m_scu_regs[36],state->m_scu_regs[38]);
|
||||
|
||||
if(scanline == 0*y_step)
|
||||
device_set_input_line_and_vector(state->m_maincpu, 0xe, (stv_irq.vblank_out) ? HOLD_LINE : CLEAR_LINE , 0x41);
|
||||
else if(scanline == 240*y_step)
|
||||
device_set_input_line_and_vector(state->m_maincpu, 0xf, (stv_irq.vblank_in) ? HOLD_LINE : CLEAR_LINE , 0x40);
|
||||
else if((scanline % y_step) == 0)
|
||||
else if((scanline % y_step) == 0 && scanline < 240*y_step)
|
||||
device_set_input_line_and_vector(state->m_maincpu, 0xd, (stv_irq.hblank_in) ? HOLD_LINE : CLEAR_LINE, 0x42);
|
||||
|
||||
if((state->m_scu_regs[38] & 0x81) == 0x01 && scanline == 64)
|
||||
if((state->m_scu_regs[38] & 0x81) == 0x01 && ((scanline % y_step) == 0) && scanline < 240*y_step)
|
||||
device_set_input_line_and_vector(state->m_maincpu, 0xb, (stv_irq.timer_1) ? HOLD_LINE : CLEAR_LINE, 0x44 );
|
||||
|
||||
if(scanline == (state->m_scu_regs[36] & 0x3ff)*y_step)
|
||||
@ -2580,132 +2570,6 @@ static TIMER_DEVICE_CALLBACK( saturn_scanline )
|
||||
device_set_input_line_and_vector(state->m_maincpu, 0x2, (stv_irq.vdp1_end) ? HOLD_LINE : CLEAR_LINE, 0x4d);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static timer_device *vblank_out_timer,*scan_timer,*t1_timer;
|
||||
static int h_sync,v_sync;
|
||||
static int cur_scan;
|
||||
|
||||
#define VBLANK_OUT_IRQ(m) \
|
||||
timer_0 = 0; \
|
||||
{ \
|
||||
/*if(LOG_IRQ) logerror ("Interrupt: VBlank-OUT Vector 0x41 Level 0x0e\n");*/ \
|
||||
cputag_set_input_line_and_vector(m, "maincpu", 0xe, (stv_irq.vblank_out) ? HOLD_LINE : CLEAR_LINE , 0x41); \
|
||||
} \
|
||||
|
||||
#define VBLANK_IN_IRQ \
|
||||
{ \
|
||||
/*if(LOG_IRQ) logerror ("Interrupt: VBlank IN Vector 0x40 Level 0x0f\n");*/ \
|
||||
cputag_set_input_line_and_vector(device->machine(), "maincpu", 0xf, (stv_irq.vblank_in) ? HOLD_LINE : CLEAR_LINE , 0x40); \
|
||||
} \
|
||||
|
||||
#define HBLANK_IN_IRQ(m) \
|
||||
timer_1 = state->m_scu_regs[37] & 0x1ff; \
|
||||
{ \
|
||||
/*if(LOG_IRQ) logerror ("Interrupt: HBlank-In at scanline %04x, Vector 0x42 Level 0x0d\n",scanline);*/ \
|
||||
cputag_set_input_line_and_vector(m, "maincpu", 0xd, (stv_irq.hblank_in) ? HOLD_LINE : CLEAR_LINE, 0x42); \
|
||||
} \
|
||||
|
||||
#define TIMER_0_IRQ(m) \
|
||||
if(timer_0 == (state->m_scu_regs[36] & 0x3ff)) \
|
||||
{ \
|
||||
/*if(LOG_IRQ) logerror ("Interrupt: Timer 0 at scanline %04x, Vector 0x43 Level 0x0c\n",scanline);*/ \
|
||||
cputag_set_input_line_and_vector(m, "maincpu", 0xc, (stv_irq.timer_0) ? HOLD_LINE : CLEAR_LINE, 0x43 ); \
|
||||
} \
|
||||
|
||||
#define TIMER_1_IRQ(m) \
|
||||
if((state->m_scu_regs[38] & 1)) \
|
||||
{ \
|
||||
if(!(state->m_scu_regs[38] & 0x80)) \
|
||||
{ \
|
||||
/*if(LOG_IRQ) logerror ("Interrupt: Timer 1 at point %04x, Vector 0x44 Level 0x0b\n",point);*/ \
|
||||
cputag_set_input_line_and_vector(m, "maincpu", 0xb, (stv_irq.timer_1) ? HOLD_LINE : CLEAR_LINE, 0x44 ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if((timer_0) == (state->m_scu_regs[36] & 0x3ff)) \
|
||||
{ \
|
||||
/*if(LOG_IRQ) logerror ("Interrupt: Timer 1 at point %04x, Vector 0x44 Level 0x0b\n",point);*/ \
|
||||
cputag_set_input_line_and_vector(m, "maincpu", 0xb, (stv_irq.timer_1) ? HOLD_LINE : CLEAR_LINE, 0x44 ); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
|
||||
#define VDP1_IRQ \
|
||||
{ \
|
||||
cputag_set_input_line_and_vector(machine, "maincpu", 2, (stv_irq.vdp1_end) ? HOLD_LINE : CLEAR_LINE, 0x4d); \
|
||||
} \
|
||||
|
||||
static TIMER_DEVICE_CALLBACK( hblank_in_irq )
|
||||
{
|
||||
saturn_state *state = timer.machine().driver_data<saturn_state>();
|
||||
int scanline = param;
|
||||
|
||||
// h = timer.machine().primary_screen->height();
|
||||
// w = timer.machine().primary_screen->width();
|
||||
|
||||
HBLANK_IN_IRQ(timer.machine());
|
||||
TIMER_0_IRQ(timer.machine());
|
||||
|
||||
if(scanline+1 < v_sync)
|
||||
{
|
||||
if(stv_irq.hblank_in || stv_irq.timer_0)
|
||||
scan_timer->adjust(timer.machine().primary_screen->time_until_pos(scanline+1, h_sync), scanline+1);
|
||||
/*set the first Timer-1 event*/
|
||||
cur_scan = scanline+1;
|
||||
if(stv_irq.timer_1)
|
||||
t1_timer->adjust(timer.machine().primary_screen->time_until_pos(scanline+1, timer_1), scanline+1);
|
||||
}
|
||||
|
||||
timer_0++;
|
||||
}
|
||||
|
||||
static TIMER_DEVICE_CALLBACK( timer1_irq )
|
||||
{
|
||||
saturn_state *state = timer.machine().driver_data<saturn_state>();
|
||||
int scanline = param;
|
||||
|
||||
TIMER_1_IRQ(timer.machine());
|
||||
|
||||
if(stv_irq.timer_1)
|
||||
t1_timer->adjust(timer.machine().primary_screen->time_until_pos(scanline+1, timer_1), scanline+1);
|
||||
}
|
||||
|
||||
static TIMER_CALLBACK( vdp1_irq )
|
||||
{
|
||||
VDP1_IRQ;
|
||||
}
|
||||
|
||||
static TIMER_DEVICE_CALLBACK( vblank_out_irq )
|
||||
{
|
||||
VBLANK_OUT_IRQ(timer.machine());
|
||||
}
|
||||
|
||||
/*V-Blank-IN event*/
|
||||
static INTERRUPT_GEN( stv_interrupt )
|
||||
{
|
||||
// scanline = 0;
|
||||
rectangle visarea = device->machine().primary_screen->visible_area();
|
||||
|
||||
h_sync = visarea.max_x+1;//horz
|
||||
v_sync = visarea.max_y+1;//vert
|
||||
|
||||
VBLANK_IN_IRQ;
|
||||
|
||||
/*Next V-Blank-OUT event*/
|
||||
if(stv_irq.vblank_out)
|
||||
vblank_out_timer->adjust(device->machine().primary_screen->time_until_pos(0));
|
||||
/*Set the first Hblank-IN event*/
|
||||
if(stv_irq.hblank_in || stv_irq.timer_0 || stv_irq.timer_1)
|
||||
scan_timer->adjust(device->machine().primary_screen->time_until_pos(0, h_sync));
|
||||
|
||||
/*TODO: timing of this one (related to the VDP1 speed)*/
|
||||
/* (NOTE: value shouldn't be at h_sync/v_sync position (will break shienryu))*/
|
||||
device->machine().scheduler().timer_set(device->machine().primary_screen->time_until_pos(0), FUNC(vdp1_irq));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static MACHINE_RESET( saturn )
|
||||
{
|
||||
saturn_state *state = machine.driver_data<saturn_state>();
|
||||
@ -2731,16 +2595,6 @@ static MACHINE_RESET( saturn )
|
||||
machine.device("audiocpu")->set_unscaled_clock(MASTER_CLOCK_320/5);
|
||||
|
||||
stvcd_reset( machine );
|
||||
|
||||
/* set the first scanline 0 timer to go off */
|
||||
#if NEW_IRQ_CODE
|
||||
#else
|
||||
scan_timer = machine.device<timer_device>("scan_timer");
|
||||
t1_timer = machine.device<timer_device>("t1_timer");
|
||||
vblank_out_timer = machine.device<timer_device>("vbout_timer");
|
||||
vblank_out_timer->adjust(machine.primary_screen->time_until_pos(0));
|
||||
scan_timer->adjust(machine.primary_screen->time_until_pos(224, 352));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -2767,17 +2621,6 @@ static MACHINE_RESET( stv )
|
||||
|
||||
stvcd_reset(machine);
|
||||
|
||||
/* set the first scanline 0 timer to go off */
|
||||
#if NEW_IRQ_CODE
|
||||
|
||||
#else
|
||||
scan_timer = machine.device<timer_device>("scan_timer");
|
||||
t1_timer = machine.device<timer_device>("t1_timer");
|
||||
vblank_out_timer = machine.device<timer_device>("vbout_timer");
|
||||
vblank_out_timer->adjust(machine.primary_screen->time_until_pos(0));
|
||||
scan_timer->adjust(machine.primary_screen->time_until_pos(224, 352));
|
||||
#endif
|
||||
|
||||
state->m_stv_rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
|
||||
state->m_prev_bankswitch = 0xff;
|
||||
}
|
||||
@ -2789,11 +2632,7 @@ static MACHINE_CONFIG_START( saturn, driver_device )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
|
||||
MCFG_CPU_PROGRAM_MAP(saturn_mem)
|
||||
#if NEW_IRQ_CODE
|
||||
MCFG_TIMER_ADD_SCANLINE("scantimer", saturn_scanline, "screen", 0, 1)
|
||||
#else
|
||||
MCFG_CPU_VBLANK_INT("screen",stv_interrupt)
|
||||
#endif
|
||||
MCFG_CPU_CONFIG(sh2_conf_master)
|
||||
|
||||
MCFG_CPU_ADD("slave", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
|
||||
@ -2808,22 +2647,12 @@ static MACHINE_CONFIG_START( saturn, driver_device )
|
||||
|
||||
MCFG_NVRAM_HANDLER(saturn)
|
||||
|
||||
#if NEW_IRQ_CODE
|
||||
|
||||
#else
|
||||
MCFG_TIMER_ADD("scan_timer", hblank_in_irq)
|
||||
MCFG_TIMER_ADD("t1_timer", timer1_irq)
|
||||
MCFG_TIMER_ADD("vbout_timer", vblank_out_irq)
|
||||
#endif
|
||||
MCFG_TIMER_ADD("sector_timer", stv_sector_cb)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(192)) // guess, needed to force video update after V-Blank OUT interrupt
|
||||
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB15)
|
||||
MCFG_SCREEN_SIZE(704*2, 512*2)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0*8, 703, 0*8, 511) // we need to use a resolution as high as the max size it can change to
|
||||
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_320/8, 464, 0, 320, 263, 0, 224)
|
||||
MCFG_SCREEN_UPDATE(stv_vdp2)
|
||||
|
||||
MCFG_PALETTE_LENGTH(2048+(2048*2))//standard palette + extra memory for rgb brightness.
|
||||
@ -2848,11 +2677,7 @@ static MACHINE_CONFIG_START( stv, driver_device )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
|
||||
MCFG_CPU_PROGRAM_MAP(stv_mem)
|
||||
#if NEW_IRQ_CODE
|
||||
MCFG_TIMER_ADD_SCANLINE("scantimer", saturn_scanline, "screen", 0, 1)
|
||||
#else
|
||||
MCFG_CPU_VBLANK_INT("screen",stv_interrupt)
|
||||
#endif
|
||||
MCFG_CPU_CONFIG(sh2_conf_master)
|
||||
|
||||
MCFG_CPU_ADD("slave", SH2, MASTER_CLOCK_352/2) // 28.6364 MHz
|
||||
@ -2867,13 +2692,6 @@ static MACHINE_CONFIG_START( stv, driver_device )
|
||||
|
||||
MCFG_EEPROM_93C46_ADD("eeprom") /* Actually 93c45 */
|
||||
|
||||
#if NEW_IRQ_CODE
|
||||
|
||||
#else
|
||||
MCFG_TIMER_ADD("scan_timer", hblank_in_irq)
|
||||
MCFG_TIMER_ADD("t1_timer", timer1_irq)
|
||||
MCFG_TIMER_ADD("vbout_timer", vblank_out_irq)
|
||||
#endif
|
||||
MCFG_TIMER_ADD("sector_timer", stv_sector_cb)
|
||||
|
||||
/* video hardware */
|
||||
@ -2881,7 +2699,7 @@ static MACHINE_CONFIG_START( stv, driver_device )
|
||||
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB15)
|
||||
MCFG_SCREEN_RAW_PARAMS(PIXEL_CLOCK, 400, 0, 320, 262, 0, 224)
|
||||
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_320/8, 464, 0, 320, 263, 0, 224)
|
||||
MCFG_SCREEN_UPDATE(stv_vdp2)
|
||||
|
||||
MCFG_PALETTE_LENGTH(2048+(2048*2))//standard palette + extra memory for rgb brightness.
|
||||
|
@ -89,6 +89,8 @@ public:
|
||||
legacy_cpu_device* m_audiocpu;
|
||||
};
|
||||
|
||||
#define MASTER_CLOCK_352 57272800
|
||||
#define MASTER_CLOCK_320 53748200
|
||||
|
||||
DRIVER_INIT ( stv );
|
||||
|
||||
|
@ -108,6 +108,7 @@ In other words,the first three types uses the offset and not the color allocated
|
||||
static UINT8 get_hblank(running_machine &machine);
|
||||
static int get_vblank_duration(running_machine &machine);
|
||||
static int get_hblank_duration(running_machine &machine);
|
||||
static int get_pixel_clock(running_machine &machine);
|
||||
static UINT8 get_odd_bit(running_machine &machine);
|
||||
|
||||
static void refresh_palette_data(running_machine &machine);
|
||||
@ -5317,44 +5318,15 @@ WRITE32_HANDLER ( saturn_vdp2_regs_w )
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 get_hblank(running_machine &machine)
|
||||
{
|
||||
static int cur_h;
|
||||
|
||||
const rectangle &visarea = machine.primary_screen->visible_area();
|
||||
cur_h = machine.primary_screen->hpos();
|
||||
|
||||
if (cur_h > visarea.max_x)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the following is a complete guess-work */
|
||||
static int get_hblank_duration(running_machine &machine)
|
||||
{
|
||||
saturn_state *state = machine.driver_data<saturn_state>();
|
||||
switch( STV_VDP2_HRES & 3 )
|
||||
{
|
||||
case 0: return 80; //400-320
|
||||
case 1: return 104; //456-352
|
||||
case 2: return 160; //(400-320)*2
|
||||
case 3: return 208; //(456-352)*2
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
if(STV_VDP2_HRES & 2)
|
||||
return 464*2;
|
||||
|
||||
UINT8 stv_get_vblank(running_machine &machine)
|
||||
{
|
||||
static int cur_v;
|
||||
const rectangle &visarea = machine.primary_screen->visible_area();
|
||||
cur_v = machine.primary_screen->vpos();
|
||||
|
||||
if (cur_v > visarea.max_y)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return 464;
|
||||
}
|
||||
|
||||
/*some vblank lines measurements (according to Charles MacDonald)*/
|
||||
@ -5362,19 +5334,71 @@ static int get_vblank_duration(running_machine &machine)
|
||||
{
|
||||
saturn_state *state = machine.driver_data<saturn_state>();
|
||||
|
||||
/* TODO: interlace mode "eats" one line, should be 262.5 */
|
||||
|
||||
if(STV_VDP2_HRES & 4)
|
||||
return (STV_VDP2_HRES & 1) ? 480+82 : 480+45; //Hi-Vision / 31kHz Monitor
|
||||
return (STV_VDP2_HRES & 1) ? 561 : 525; //Hi-Vision / 31kHz Monitor
|
||||
|
||||
if((STV_VDP2_LSMD & 3) == 3)
|
||||
return 264*2;
|
||||
return 263*2;
|
||||
|
||||
return 264;
|
||||
return 263;
|
||||
}
|
||||
|
||||
static int get_pixel_clock(running_machine &machine)
|
||||
{
|
||||
saturn_state *state = machine.driver_data<saturn_state>();
|
||||
int res,divider;
|
||||
|
||||
res = state->m_vdp2.pixel_clock ? MASTER_CLOCK_320 : MASTER_CLOCK_352;
|
||||
/* TODO: divider is ALWAYS 8, this thing is just to over-compensate for MAME framework faults ... */
|
||||
divider = 8;
|
||||
|
||||
if(STV_VDP2_HRES & 2)
|
||||
divider>>=1;
|
||||
|
||||
if((STV_VDP2_LSMD & 3) == 3)
|
||||
divider>>=1;
|
||||
|
||||
if(STV_VDP2_HRES & 4) //TODO
|
||||
divider>>=1;
|
||||
|
||||
return res/divider;
|
||||
}
|
||||
|
||||
static UINT8 get_hblank(running_machine &machine)
|
||||
{
|
||||
static int cur_h;
|
||||
const rectangle &visarea = machine.primary_screen->visible_area();
|
||||
cur_h = machine.primary_screen->hpos();
|
||||
|
||||
if (cur_h > visarea.max_x) //TODO
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT8 stv_get_vblank(running_machine &machine)
|
||||
{
|
||||
saturn_state *state = machine.driver_data<saturn_state>();
|
||||
int cur_v,vblank;
|
||||
cur_v = machine.primary_screen->vpos();
|
||||
|
||||
vblank = 240;
|
||||
|
||||
if((STV_VDP2_LSMD & 3) == 3)
|
||||
vblank<<=1;
|
||||
|
||||
if (cur_v >= vblank)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT8 get_odd_bit(running_machine &machine)
|
||||
{
|
||||
saturn_state *state = machine.driver_data<saturn_state>();
|
||||
static int cur_v;
|
||||
int cur_v;
|
||||
cur_v = machine.primary_screen->vpos();
|
||||
|
||||
if(STV_VDP2_HRES & 4) //exclusive monitor mode makes this bit to be always 1
|
||||
@ -5382,8 +5406,8 @@ static UINT8 get_odd_bit(running_machine &machine)
|
||||
|
||||
if(cur_v % 2)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stv_vdp2_state_save_postload(running_machine &machine)
|
||||
@ -5502,13 +5526,14 @@ void stv_vdp2_dynamic_res_change(running_machine &machine)
|
||||
visarea.max_x = horz_res-1;
|
||||
visarea.min_y = 0;
|
||||
visarea.max_y = vert_res-1;
|
||||
attoseconds_t refresh;;
|
||||
|
||||
vblank_period = get_vblank_duration(machine);
|
||||
hblank_period = get_hblank_duration(machine);
|
||||
|
||||
refresh = HZ_TO_ATTOSECONDS(get_pixel_clock(machine)) * (hblank_period) * vblank_period;
|
||||
//printf("%d %d %d %d\n",horz_res,vert_res,horz_res+hblank_period,vblank_period);
|
||||
|
||||
machine.primary_screen->configure((horz_res+hblank_period), (vblank_period), visarea, machine.primary_screen->frame_period().attoseconds );
|
||||
machine.primary_screen->configure((hblank_period), (vblank_period), visarea, refresh );
|
||||
}
|
||||
// machine.primary_screen->set_visible_area(0*8, horz_res-1,0*8, vert_res-1);
|
||||
//if(LOG_VDP2) popmessage("%04d %04d",horz_res-1,vert-1);
|
||||
|
Loading…
Reference in New Issue
Block a user