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