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