more anonymous timers work (nw)

This commit is contained in:
Ivan Vangelista 2017-04-13 18:30:47 +02:00
parent 41dcf66505
commit 61ccf0d801
20 changed files with 64 additions and 25 deletions

View File

@ -36,7 +36,7 @@
Todo: Todo:
FLIPX support in taitoic.c is not quite correct - the Taito logo is wrong, FLIPX support in the video chips is not quite correct - the Taito logo is wrong,
and the floor in the Doom levels has horizontal scrolling where it shouldn't. and the floor in the Doom levels has horizontal scrolling where it shouldn't.
No networked machine support No networked machine support
@ -69,7 +69,7 @@ void gunbustr_state::device_timer(emu_timer &timer, device_timer_id id, int para
INTERRUPT_GEN_MEMBER(gunbustr_state::gunbustr_interrupt) INTERRUPT_GEN_MEMBER(gunbustr_state::gunbustr_interrupt)
{ {
timer_set(downcast<cpu_device *>(&device)->cycles_to_attotime(200000-500), TIMER_GUNBUSTR_INTERRUPT5); m_interrupt5_timer->adjust(m_maincpu->cycles_to_attotime(200000-500));
device.execute().set_input_line(4, HOLD_LINE); device.execute().set_input_line(4, HOLD_LINE);
} }
@ -140,7 +140,7 @@ READ32_MEMBER(gunbustr_state::gunbustr_gun_r)
WRITE32_MEMBER(gunbustr_state::gunbustr_gun_w) WRITE32_MEMBER(gunbustr_state::gunbustr_gun_w)
{ {
/* 10000 cycle delay is arbitrary */ /* 10000 cycle delay is arbitrary */
timer_set(downcast<cpu_device *>(&space.device())->cycles_to_attotime(10000), TIMER_GUNBUSTR_INTERRUPT5); m_interrupt5_timer->adjust(m_maincpu->cycles_to_attotime(10000));
} }
@ -428,6 +428,8 @@ DRIVER_INIT_MEMBER(gunbustr_state,gunbustr)
{ {
/* Speedup handler */ /* Speedup handler */
m_maincpu->space(AS_PROGRAM).install_read_handler(0x203acc, 0x203acf, read32_delegate(FUNC(gunbustr_state::main_cycle_r),this)); m_maincpu->space(AS_PROGRAM).install_read_handler(0x203acc, 0x203acf, read32_delegate(FUNC(gunbustr_state::main_cycle_r),this));
m_interrupt5_timer = timer_alloc(TIMER_GUNBUSTR_INTERRUPT5);
} }
DRIVER_INIT_MEMBER(gunbustr_state,gunbustrj) DRIVER_INIT_MEMBER(gunbustr_state,gunbustrj)

View File

@ -88,8 +88,10 @@ MACHINE_START_MEMBER(midzeus_state,midzeus)
timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate()); timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate());
timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate()); timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate());
gun_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midzeus_state::invasn_gun_callback),this)); gun_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midzeus_state::invasn_gun_callback), this));
gun_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midzeus_state::invasn_gun_callback),this)); gun_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midzeus_state::invasn_gun_callback), this));
m_display_irq_off_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(midzeus_state::display_irq_off), this));
save_item(NAME(gun_control)); save_item(NAME(gun_control));
save_item(NAME(gun_irq_state)); save_item(NAME(gun_irq_state));
@ -125,7 +127,7 @@ TIMER_CALLBACK_MEMBER(midzeus_state::display_irq_off)
INTERRUPT_GEN_MEMBER(midzeus_state::display_irq) INTERRUPT_GEN_MEMBER(midzeus_state::display_irq)
{ {
device.execute().set_input_line(0, ASSERT_LINE); device.execute().set_input_line(0, ASSERT_LINE);
machine().scheduler().timer_set(attotime::from_hz(30000000), timer_expired_delegate(FUNC(midzeus_state::display_irq_off),this)); m_display_irq_off_timer->adjust(attotime::from_hz(30000000));
} }
WRITE_LINE_MEMBER(midzeus2_state::zeus_irq) WRITE_LINE_MEMBER(midzeus2_state::zeus_irq)

View File

@ -67,6 +67,7 @@ public:
uint8_t m_nsc_latch; uint8_t m_nsc_latch;
uint8_t m_z80_latch; uint8_t m_z80_latch;
uint8_t m_mux_data; uint8_t m_mux_data;
emu_timer *m_z80_wait_ack_timer;
required_shared_ptr<uint8_t> m_comms_ram; required_shared_ptr<uint8_t> m_comms_ram;
@ -235,7 +236,7 @@ void nightgal_state::z80_wait_assert_cb()
// Note: cycles_to_attotime requires z80 context to work, calling for example m_subcpu as context gives a x4 cycle boost in z80 terms (reads execute_cycles_to_clocks() from NCS?) even if they runs at same speed basically. // Note: cycles_to_attotime requires z80 context to work, calling for example m_subcpu as context gives a x4 cycle boost in z80 terms (reads execute_cycles_to_clocks() from NCS?) even if they runs at same speed basically.
// TODO: needs a getter that tells a given CPU how many cycles requires an executing opcode for the r/w operation, which stacks with wait state penalty for accessing this specific area. // TODO: needs a getter that tells a given CPU how many cycles requires an executing opcode for the r/w operation, which stacks with wait state penalty for accessing this specific area.
machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(4), timer_expired_delegate(FUNC(nightgal_state::z80_wait_ack_cb),this)); m_z80_wait_ack_timer->adjust(m_maincpu->cycles_to_attotime(4));
} }
READ8_MEMBER(nightgal_state::royalqn_comm_r) READ8_MEMBER(nightgal_state::royalqn_comm_r)
@ -634,6 +635,8 @@ INPUT_PORTS_END
void nightgal_state::machine_start() void nightgal_state::machine_start()
{ {
m_z80_wait_ack_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nightgal_state::z80_wait_ack_cb), this));
save_item(NAME(m_nsc_latch)); save_item(NAME(m_nsc_latch));
save_item(NAME(m_z80_latch)); save_item(NAME(m_z80_latch));
save_item(NAME(m_mux_data)); save_item(NAME(m_mux_data));

View File

@ -246,7 +246,7 @@ Stephh's notes (based on the game M68000 code and some tests) :
* all reference to TAITO and "Operation Wolf" have been changed or "blanked" * all reference to TAITO and "Operation Wolf" have been changed or "blanked"
* "(c) 1988 BEAR CORPORATION KOREA" / "ALL RIGHTS RESERVED" * "(c) 1988 BEAR CORPORATION KOREA" / "ALL RIGHTS RESERVED"
* ROM check test "noped" (code at 0x00bb72) * ROM check test "noped" (code at 0x00bb72)
- Notes on bootleg c-chip (similar to what is in machine/opwolf.c) : - Notes on bootleg c-chip (similar to what is in machine/opwolf.cpp) :
* always Engish language (thus the Dip Switch change to "Unused") * always Engish language (thus the Dip Switch change to "Unused")
* round 4 in "demo mode" instead of round 5 * round 4 in "demo mode" instead of round 5
* "service" button doesn't add credits (it works in the "test mode" though) * "service" button doesn't add credits (it works in the "test mode" though)
@ -439,6 +439,8 @@ ADDRESS_MAP_END
void opwolf_state::machine_start() void opwolf_state::machine_start()
{ {
m_opwolf_timer = timer_alloc(TIMER_OPWOLF);
save_item(NAME(m_sprite_ctrl)); save_item(NAME(m_sprite_ctrl));
save_item(NAME(m_sprites_flipscreen)); save_item(NAME(m_sprites_flipscreen));

View File

@ -423,7 +423,7 @@ WRITE16_MEMBER(othunder_state::othunder_lightgun_w)
The ADC60808 clock is 512kHz. Conversion takes between 0 and 8 clock The ADC60808 clock is 512kHz. Conversion takes between 0 and 8 clock
cycles, so would end in a maximum of 15.625us. We'll use 10. */ cycles, so would end in a maximum of 15.625us. We'll use 10. */
timer_set(attotime::from_usec(10), TIMER_AD_INTERRUPT); m_ad_interrupt_timer->adjust(attotime::from_usec(10));
} }
@ -662,6 +662,8 @@ void othunder_state::machine_start()
{ {
membank("z80bank")->configure_entries(0, 4, memregion("audiocpu")->base(), 0x4000); membank("z80bank")->configure_entries(0, 4, memregion("audiocpu")->base(), 0x4000);
m_ad_interrupt_timer = timer_alloc(TIMER_AD_INTERRUPT);
save_item(NAME(m_vblank_irq)); save_item(NAME(m_vblank_irq));
save_item(NAME(m_ad_irq)); save_item(NAME(m_ad_irq));
save_item(NAME(m_pan)); save_item(NAME(m_pan));

View File

@ -121,7 +121,7 @@ void policetr_state::device_timer(emu_timer &timer, device_timer_id id, int para
INTERRUPT_GEN_MEMBER(policetr_state::irq4_gen) INTERRUPT_GEN_MEMBER(policetr_state::irq4_gen)
{ {
device.execute().set_input_line(R3000_IRQ4, ASSERT_LINE); device.execute().set_input_line(R3000_IRQ4, ASSERT_LINE);
timer_set(m_screen->time_until_pos(0), TIMER_IRQ5_GEN); m_irq5_gen_timer->adjust(m_screen->time_until_pos(0));
} }
@ -386,6 +386,10 @@ static INPUT_PORTS_START( sshoot11 )
INPUT_PORTS_END INPUT_PORTS_END
void policetr_state::machine_start()
{
m_irq5_gen_timer = timer_alloc(TIMER_IRQ5_GEN);
}
/************************************* /*************************************
* *

View File

@ -69,7 +69,7 @@ void rollerg_state::device_timer(emu_timer &timer, device_timer_id id, int param
WRITE8_MEMBER(rollerg_state::sound_arm_nmi_w) WRITE8_MEMBER(rollerg_state::sound_arm_nmi_w)
{ {
m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
timer_set(attotime::from_usec(50), TIMER_NMI); /* kludge until the K053260 is emulated correctly */ m_nmi_timer->adjust(attotime::from_usec(50)); /* kludge until the K053260 is emulated correctly */
} }
READ8_MEMBER(rollerg_state::pip_r) READ8_MEMBER(rollerg_state::pip_r)
@ -226,6 +226,8 @@ void rollerg_state::machine_start()
membank("bank1")->configure_entries(6, 2, &ROM[0x10000], 0x4000); membank("bank1")->configure_entries(6, 2, &ROM[0x10000], 0x4000);
membank("bank1")->set_entry(0); membank("bank1")->set_entry(0);
m_nmi_timer = timer_alloc(TIMER_NMI);
save_item(NAME(m_readzoomroms)); save_item(NAME(m_readzoomroms));
} }

View File

@ -102,6 +102,8 @@ TO DO :
void tehkanwc_state::machine_start() void tehkanwc_state::machine_start()
{ {
m_reset_timer = timer_alloc(TIMER_RESET);
save_item(NAME(m_track0)); save_item(NAME(m_track0));
save_item(NAME(m_track1)); save_item(NAME(m_track1));
save_item(NAME(m_msm_data_offs)); save_item(NAME(m_msm_data_offs));
@ -175,7 +177,7 @@ WRITE8_MEMBER(tehkanwc_state::sound_answer_w)
/* in Gridiron, the sound CPU goes in a tight loop after the self test, */ /* in Gridiron, the sound CPU goes in a tight loop after the self test, */
/* probably waiting to be reset by a watchdog */ /* probably waiting to be reset by a watchdog */
if (space.device().safe_pc() == 0x08bc) timer_set(attotime::from_seconds(1), TIMER_RESET); if (space.device().safe_pc() == 0x08bc) m_reset_timer->adjust(attotime::from_seconds(1));
} }

View File

@ -313,7 +313,7 @@ WRITE8_MEMBER(thunderx_state::thunderx_1f98_w)
calculate_collisions(); calculate_collisions();
/* 100 cycle delay is arbitrary */ /* 100 cycle delay is arbitrary */
timer_set(downcast<cpu_device *>(&space.device())->cycles_to_attotime(100), TIMER_THUNDERX_FIRQ); m_thunderx_firq_timer->adjust(m_maincpu->cycles_to_attotime(100));
} }
m_1f98_latch = data; m_1f98_latch = data;
@ -1034,15 +1034,19 @@ ROM_START( crazycop )
ROM_END ROM_END
DRIVER_INIT_MEMBER(thunderx_state, thunderx)
{
m_thunderx_firq_timer = timer_alloc(TIMER_THUNDERX_FIRQ);
}
/***************************************************************************/ /***************************************************************************/
GAME( 1988, scontra, 0, scontra, scontra, driver_device, 0, ROT90, "Konami", "Super Contra", MACHINE_SUPPORTS_SAVE ) GAME( 1988, scontra, 0, scontra, scontra, driver_device, 0, ROT90, "Konami", "Super Contra", MACHINE_SUPPORTS_SAVE )
GAME( 1988, scontraj, scontra, scontra, scontra, driver_device, 0, ROT90, "Konami", "Super Contra (Japan)", MACHINE_SUPPORTS_SAVE ) GAME( 1988, scontraj, scontra, scontra, scontra, driver_device, 0, ROT90, "Konami", "Super Contra (Japan)", MACHINE_SUPPORTS_SAVE )
GAME( 1988, thunderx, 0, thunderx, thunderx, driver_device, 0, ROT0, "Konami", "Thunder Cross (set 1)", MACHINE_SUPPORTS_SAVE ) GAME( 1988, thunderx, 0, thunderx, thunderx, thunderx_state, thunderx, ROT0, "Konami", "Thunder Cross (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1988, thunderxa, thunderx, thunderx, thunderx, driver_device, 0, ROT0, "Konami", "Thunder Cross (set 2)", MACHINE_SUPPORTS_SAVE ) GAME( 1988, thunderxa, thunderx, thunderx, thunderx, thunderx_state, thunderx, ROT0, "Konami", "Thunder Cross (set 2)", MACHINE_SUPPORTS_SAVE )
GAME( 1988, thunderxb, thunderx, thunderx, thunderx, driver_device, 0, ROT0, "Konami", "Thunder Cross (set 3)", MACHINE_SUPPORTS_SAVE ) GAME( 1988, thunderxb, thunderx, thunderx, thunderx, thunderx_state, thunderx, ROT0, "Konami", "Thunder Cross (set 3)", MACHINE_SUPPORTS_SAVE )
GAME( 1988, thunderxj, thunderx, thunderx, thnderxj, driver_device, 0, ROT0, "Konami", "Thunder Cross (Japan)", MACHINE_SUPPORTS_SAVE ) GAME( 1988, thunderxj, thunderx, thunderx, thnderxj, thunderx_state, thunderx, ROT0, "Konami", "Thunder Cross (Japan)", MACHINE_SUPPORTS_SAVE )
GAME( 1988, gbusters, 0, gbusters, gbusters, driver_device, 0, ROT90, "Konami", "Gang Busters (set 1)", MACHINE_SUPPORTS_SAVE ) /* N02 & J03 program roms */ GAME( 1988, gbusters, 0, gbusters, gbusters, driver_device, 0, ROT90, "Konami", "Gang Busters (set 1)", MACHINE_SUPPORTS_SAVE ) /* N02 & J03 program roms */
GAME( 1988, gbustersa, gbusters, gbusters, gbusters, driver_device, 0, ROT90, "Konami", "Gang Busters (set 2)", MACHINE_SUPPORTS_SAVE ) /* unknown region program roms */ GAME( 1988, gbustersa, gbusters, gbusters, gbusters, driver_device, 0, ROT90, "Konami", "Gang Busters (set 2)", MACHINE_SUPPORTS_SAVE ) /* unknown region program roms */
GAME( 1988, crazycop, gbusters, gbusters, gbusters, driver_device, 0, ROT90, "Konami", "Crazy Cop (Japan)", MACHINE_SUPPORTS_SAVE ) /* M02 & J03 program roms */ GAME( 1988, crazycop, gbusters, gbusters, gbusters, driver_device, 0, ROT90, "Konami", "Crazy Cop (Japan)", MACHINE_SUPPORTS_SAVE ) /* M02 & J03 program roms */

View File

@ -89,7 +89,7 @@ WRITE8_MEMBER(trucocl_state::audio_dac_w)
m_dac->write(rom[dac_address+m_cur_dac_address_index]); m_dac->write(rom[dac_address+m_cur_dac_address_index]);
timer_set( attotime::from_hz( 16000 ), TIMER_DAC_IRQ); m_dac_irq_timer->adjust(attotime::from_hz( 16000 ));
} }
static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, trucocl_state ) static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, trucocl_state )
@ -200,6 +200,8 @@ DRIVER_INIT_MEMBER(trucocl_state,trucocl)
{ {
m_cur_dac_address = -1; m_cur_dac_address = -1;
m_cur_dac_address_index = 0; m_cur_dac_address_index = 0;
m_dac_irq_timer = timer_alloc(TIMER_DAC_IRQ);
} }

View File

@ -49,6 +49,7 @@ public:
uint16_t m_coin_word; uint16_t m_coin_word;
std::unique_ptr<gb_tempsprite[]> m_spritelist; std::unique_ptr<gb_tempsprite[]> m_spritelist;
uint32_t m_mem[2]; uint32_t m_mem[2];
emu_timer *m_interrupt5_timer;
DECLARE_WRITE32_MEMBER(gunbustr_input_w); DECLARE_WRITE32_MEMBER(gunbustr_input_w);
DECLARE_WRITE32_MEMBER(motor_control_w); DECLARE_WRITE32_MEMBER(motor_control_w);

View File

@ -36,6 +36,8 @@ public:
required_device<screen_device> m_screen; required_device<screen_device> m_screen;
optional_device<palette_device> m_palette; optional_device<palette_device> m_palette;
emu_timer *m_display_irq_off_timer;
DECLARE_WRITE32_MEMBER(cmos_w); DECLARE_WRITE32_MEMBER(cmos_w);
DECLARE_READ32_MEMBER(cmos_r); DECLARE_READ32_MEMBER(cmos_r);
DECLARE_WRITE32_MEMBER(cmos_protect_w); DECLARE_WRITE32_MEMBER(cmos_protect_w);

View File

@ -45,6 +45,8 @@ public:
int m_opwolf_gun_xoffs; int m_opwolf_gun_xoffs;
int m_opwolf_gun_yoffs; int m_opwolf_gun_yoffs;
emu_timer *m_opwolf_timer;
/* c-chip */ /* c-chip */
emu_timer *m_cchip_timer; emu_timer *m_cchip_timer;

View File

@ -62,6 +62,7 @@ public:
int m_vblank_irq; int m_vblank_irq;
int m_ad_irq; int m_ad_irq;
int m_pan[4]; int m_pan[4];
emu_timer *m_ad_interrupt_timer;
/* devices */ /* devices */
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;

View File

@ -44,6 +44,7 @@ public:
uint16_t m_dst_yoffs; uint16_t m_dst_yoffs;
uint8_t m_video_latch; uint8_t m_video_latch;
uint32_t m_srcbitmap_height_mask; uint32_t m_srcbitmap_height_mask;
emu_timer *m_irq5_gen_timer;
DECLARE_WRITE32_MEMBER(control_w); DECLARE_WRITE32_MEMBER(control_w);
DECLARE_WRITE32_MEMBER(policetr_bsmt2000_reg_w); DECLARE_WRITE32_MEMBER(policetr_bsmt2000_reg_w);
DECLARE_WRITE32_MEMBER(policetr_bsmt2000_data_w); DECLARE_WRITE32_MEMBER(policetr_bsmt2000_data_w);
@ -58,6 +59,7 @@ public:
DECLARE_DRIVER_INIT(policetr); DECLARE_DRIVER_INIT(policetr);
DECLARE_DRIVER_INIT(sshooter); DECLARE_DRIVER_INIT(sshooter);
DECLARE_DRIVER_INIT(plctr13b); DECLARE_DRIVER_INIT(plctr13b);
virtual void machine_start() override;
virtual void video_start() override; virtual void video_start() override;
uint32_t screen_update_policetr(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_policetr(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(irq4_gen); INTERRUPT_GEN_MEMBER(irq4_gen);

View File

@ -29,6 +29,7 @@ public:
/* misc */ /* misc */
int m_readzoomroms; int m_readzoomroms;
emu_timer *m_nmi_timer;
/* devices */ /* devices */
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;

View File

@ -50,6 +50,7 @@ public:
uint8_t m_led1; uint8_t m_led1;
tilemap_t *m_bg_tilemap; tilemap_t *m_bg_tilemap;
tilemap_t *m_fg_tilemap; tilemap_t *m_fg_tilemap;
emu_timer *m_reset_timer;
DECLARE_WRITE8_MEMBER(sub_cpu_halt_w); DECLARE_WRITE8_MEMBER(sub_cpu_halt_w);
DECLARE_READ8_MEMBER(track_0_r); DECLARE_READ8_MEMBER(track_0_r);

View File

@ -48,6 +48,7 @@ public:
/* misc */ /* misc */
int m_priority; int m_priority;
uint8_t m_1f98_latch; uint8_t m_1f98_latch;
emu_timer *m_thunderx_firq_timer;
DECLARE_WRITE8_MEMBER(scontra_bankswitch_w); DECLARE_WRITE8_MEMBER(scontra_bankswitch_w);
DECLARE_WRITE8_MEMBER(thunderx_videobank_w); DECLARE_WRITE8_MEMBER(thunderx_videobank_w);
@ -65,6 +66,7 @@ public:
virtual void machine_start() override; virtual void machine_start() override;
virtual void machine_reset() override; virtual void machine_reset() override;
virtual void video_start() override; virtual void video_start() override;
DECLARE_DRIVER_INIT(thunderx);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_interrupt); INTERRUPT_GEN_MEMBER(vblank_interrupt);

View File

@ -25,6 +25,8 @@ public:
tilemap_t *m_bg_tilemap; tilemap_t *m_bg_tilemap;
uint8_t m_irq_mask; uint8_t m_irq_mask;
emu_timer *m_dac_irq_timer;
DECLARE_WRITE8_MEMBER(irq_enable_w); DECLARE_WRITE8_MEMBER(irq_enable_w);
DECLARE_WRITE8_MEMBER(trucocl_videoram_w); DECLARE_WRITE8_MEMBER(trucocl_videoram_w);
DECLARE_WRITE8_MEMBER(trucocl_colorram_w); DECLARE_WRITE8_MEMBER(trucocl_colorram_w);

View File

@ -1070,7 +1070,7 @@ TIMER_CALLBACK_MEMBER(opwolf_state::cchip_timer)
{ {
// Simulate time for command to execute (exact timing unknown, this is close) // Simulate time for command to execute (exact timing unknown, this is close)
m_current_cmd = 0xf5; m_current_cmd = 0xf5;
timer_set(m_maincpu->cycles_to_attotime(80000), TIMER_OPWOLF); m_opwolf_timer->adjust(m_maincpu->cycles_to_attotime(80000));
} }
m_cchip_last_7a = m_cchip_ram[0x7a]; m_cchip_last_7a = m_cchip_ram[0x7a];