comparison gen_player.c @ 1983:a7b753e260a2 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 09 May 2020 23:39:44 -0700
parents bd70f1e15684
children a042e046f7f2
comparison
equal deleted inserted replaced
1937:cafde1255ad3 1983:a7b753e260a2
1 #include "gen_player.h"
2 #include "event_log.h"
3 #include "render.h"
4
5 #ifdef IS_LIB
6 #define MAX_SOUND_CYCLES (MCLKS_PER_YM*NUM_OPERATORS*6*4)
7 #else
8 #define MAX_SOUND_CYCLES 100000
9 #endif
10
11 static void sync_sound(gen_player *gen, uint32_t target)
12 {
13 //printf("YM | Cycle: %d, bpos: %d, PSG | Cycle: %d, bpos: %d\n", gen->ym->current_cycle, gen->ym->buffer_pos, gen->psg->cycles, gen->psg->buffer_pos * 2);
14 while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) {
15 uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES;
16 //printf("Running PSG to cycle %d\n", cur_target);
17 psg_run(gen->psg, cur_target);
18 //printf("Running YM-2612 to cycle %d\n", cur_target);
19 ym_run(gen->ym, cur_target);
20 }
21 psg_run(gen->psg, target);
22 ym_run(gen->ym, target);
23
24 //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2);
25 }
26
27 static void run(gen_player *player)
28 {
29 while(player->reader.socket || player->reader.buffer.cur_pos < player->reader.buffer.size)
30 {
31 uint32_t cycle;
32 uint8_t event = reader_next_event(&player->reader, &cycle);
33 switch (event)
34 {
35 case EVENT_FLUSH:
36 sync_sound(player, cycle);
37 vdp_run_context(player->vdp, cycle);
38 break;
39 case EVENT_ADJUST: {
40 sync_sound(player, cycle);
41 vdp_run_context(player->vdp, cycle);
42 uint32_t deduction = load_int32(&player->reader.buffer);
43 ym_adjust_cycles(player->ym, deduction);
44 vdp_adjust_cycles(player->vdp, deduction);
45 player->psg->cycles -= deduction;
46 break;
47 case EVENT_PSG_REG:
48 sync_sound(player, cycle);
49 reader_ensure_data(&player->reader, 1);
50 psg_write(player->psg, load_int8(&player->reader.buffer));
51 break;
52 case EVENT_YM_REG: {
53 sync_sound(player, cycle);
54 reader_ensure_data(&player->reader, 3);
55 uint8_t part = load_int8(&player->reader.buffer);
56 uint8_t reg = load_int8(&player->reader.buffer);
57 uint8_t value = load_int8(&player->reader.buffer);
58 if (part) {
59 ym_address_write_part2(player->ym, reg);
60 } else {
61 ym_address_write_part1(player->ym, reg);
62 }
63 ym_data_write(player->ym, value);
64 break;
65 case EVENT_STATE: {
66 reader_ensure_data(&player->reader, 3);
67 uint32_t size = load_int8(&player->reader.buffer) << 16;
68 size |= load_int16(&player->reader.buffer);
69 reader_ensure_data(&player->reader, size);
70 deserialize_buffer buffer;
71 init_deserialize(&buffer, player->reader.buffer.data + player->reader.buffer.cur_pos, size);
72 register_section_handler(&buffer, (section_handler){.fun = vdp_deserialize, .data = player->vdp}, SECTION_VDP);
73 register_section_handler(&buffer, (section_handler){.fun = ym_deserialize, .data = player->ym}, SECTION_YM2612);
74 register_section_handler(&buffer, (section_handler){.fun = psg_deserialize, .data = player->psg}, SECTION_PSG);
75 while (buffer.cur_pos < buffer.size)
76 {
77 load_section(&buffer);
78 }
79 player->reader.buffer.cur_pos += size;
80 free(buffer.handlers);
81 break;
82 }
83 default:
84 vdp_run_context(player->vdp, cycle);
85 vdp_replay_event(player->vdp, event, &player->reader);
86 }
87 }
88
89 }
90 if (!player->reader.socket) {
91 reader_ensure_data(&player->reader, 1);
92 }
93 }
94 }
95
96 static int thread_main(void *player)
97 {
98 run(player);
99 return 0;
100 }
101
102 void start_context(system_header *sys, char *statefile)
103 {
104 gen_player *player = (gen_player *)sys;
105 if (player->reader.socket) {
106 render_create_thread(&player->thread, "player", thread_main, player);
107 } else {
108 run(player);
109 }
110 }
111
112 static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
113 {
114 gen_player *player = (gen_player *)system;
115 reader_send_gamepad_event(&player->reader, gamepad_num, button, 1);
116 }
117
118 static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button)
119 {
120 gen_player *player = (gen_player *)system;
121 reader_send_gamepad_event(&player->reader, gamepad_num, button, 0);
122 }
123
124 #define MCLKS_NTSC 53693175
125 #define MCLKS_PAL 53203395
126 #define MCLKS_PER_YM 7
127 #define MCLKS_PER_Z80 15
128 #define MCLKS_PER_PSG (MCLKS_PER_Z80*16)
129
130 static void config_common(gen_player *player)
131 {
132 uint8_t vid_std = load_int8(&player->reader.buffer);
133 uint8_t name_len = load_int8(&player->reader.buffer);
134 player->header.info.name = calloc(1, name_len + 1);
135 load_buffer8(&player->reader.buffer, player->header.info.name, name_len);
136
137 player->vdp = init_vdp_context(vid_std == VID_PAL, 0);
138 render_set_video_standard(vid_std);
139 uint32_t master_clock = vid_std == VID_NTSC ? MCLKS_NTSC : MCLKS_PAL;
140
141 player->ym = malloc(sizeof(ym2612_context));
142 ym_init(player->ym, master_clock, MCLKS_PER_YM, 0);
143
144 player->psg = malloc(sizeof(psg_context));
145 psg_init(player->psg, master_clock, MCLKS_PER_PSG);
146
147 player->header.start_context = start_context;
148 player->header.gamepad_down = gamepad_down;
149 player->header.gamepad_up = gamepad_up;
150 player->header.type = SYSTEM_GENESIS_PLAYER;
151 player->header.info.save_type = SAVE_NONE;
152 }
153
154 gen_player *alloc_config_gen_player(void *stream, uint32_t rom_size)
155 {
156 uint8_t *data = stream;
157 gen_player *player = calloc(1, sizeof(gen_player));
158 init_event_reader(&player->reader, data + 9, rom_size - 9);
159 config_common(player);
160 return player;
161 }
162
163 gen_player *alloc_config_gen_player_reader(event_reader *reader)
164 {
165 gen_player *player = calloc(1, sizeof(gen_player));
166 player->reader = *reader;
167 inflateCopy(&player->reader.input_stream, &reader->input_stream);
168 render_set_external_sync(1);
169 config_common(player);
170 return player;
171 }
172