⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asap.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * asap.c - ASAP engine * * Copyright (C) 2005-2006  Piotr Fusik * * This file is part of ASAP (Another Slight Atari Player), * see http://asap.sourceforge.net * * ASAP is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * ASAP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ASAP; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include "config.h"#include <stdio.h>#include <stdlib.h>#include "asap.h"#include "asap_internal.h"#include "cpu.h"#include "pokey.h"#include "pokeysnd.h"#include "players.h"#define CMR_BASS_TABLE_OFFSET  0x70fstatic const unsigned char cmr_bass_table[] = {	0x5C, 0x56, 0x50, 0x4D, 0x47, 0x44, 0x41, 0x3E,	0x38, 0x35, 0x88, 0x7F, 0x79, 0x73, 0x6C, 0x67,	0x60, 0x5A, 0x55, 0x51, 0x4C, 0x48, 0x43, 0x3F,	0x3D, 0x39, 0x34, 0x33, 0x30, 0x2D, 0x2A, 0x28,	0x25, 0x24, 0x21, 0x1F, 0x1E};/* main clock in Hz, PAL (FREQ_17_EXACT is for NTSC!) */#define ASAP_MAIN_CLOCK  1773447UUBYTE memory[65536 + 2];int xpos = 0;int xpos_limit = 0;UBYTE wsync_halt = 0;/* structures to hold the 9 pokey control bytes */UBYTE AUDF[4 * MAXPOKEYS];	/* AUDFx (D200, D202, D204, D206) */UBYTE AUDC[4 * MAXPOKEYS];	/* AUDCx (D201, D203, D205, D207) */UBYTE AUDCTL[MAXPOKEYS];	/* AUDCTL (D208) */int Base_mult[MAXPOKEYS];		/* selects either 64Khz or 15Khz clock mult */UBYTE poly9_lookup[511];UBYTE poly17_lookup[16385];static ULONG random_scanline_counter;static unsigned int enable_stereo = 0;#ifndef SOUND_GAIN /* sound gain can be pre-defined in the configure/Makefile */#define SOUND_GAIN 4#endifstatic void POKEY_PutByte(UWORD addr, UBYTE byte){#ifdef STEREO_SOUND	addr &= enable_stereo ? 0x1f : 0x0f;#else	addr &= 0x0f;#endif	switch (addr) {	case _AUDC1:		AUDC[CHAN1] = byte;		Update_pokey_sound(_AUDC1, byte, 0, SOUND_GAIN);		break;	case _AUDC2:		AUDC[CHAN2] = byte;		Update_pokey_sound(_AUDC2, byte, 0, SOUND_GAIN);		break;	case _AUDC3:		AUDC[CHAN3] = byte;		Update_pokey_sound(_AUDC3, byte, 0, SOUND_GAIN);		break;	case _AUDC4:		AUDC[CHAN4] = byte;		Update_pokey_sound(_AUDC4, byte, 0, SOUND_GAIN);		break;	case _AUDCTL:		AUDCTL[0] = byte;		/* determine the base multiplier for the 'div by n' calculations */		if (byte & CLOCK_15)			Base_mult[0] = DIV_15;		else			Base_mult[0] = DIV_64;		Update_pokey_sound(_AUDCTL, byte, 0, SOUND_GAIN);		break;	case _AUDF1:		AUDF[CHAN1] = byte;		Update_pokey_sound(_AUDF1, byte, 0, SOUND_GAIN);		break;	case _AUDF2:		AUDF[CHAN2] = byte;		Update_pokey_sound(_AUDF2, byte, 0, SOUND_GAIN);		break;	case _AUDF3:		AUDF[CHAN3] = byte;		Update_pokey_sound(_AUDF3, byte, 0, SOUND_GAIN);		break;	case _AUDF4:		AUDF[CHAN4] = byte;		Update_pokey_sound(_AUDF4, byte, 0, SOUND_GAIN);		break;	case _STIMER:		Update_pokey_sound(_STIMER, byte, 0, SOUND_GAIN);		break;#ifdef STEREO_SOUND	case _AUDC1 + _POKEY2:		AUDC[CHAN1 + CHIP2] = byte;		Update_pokey_sound(_AUDC1, byte, 1, SOUND_GAIN);		break;	case _AUDC2 + _POKEY2:		AUDC[CHAN2 + CHIP2] = byte;		Update_pokey_sound(_AUDC2, byte, 1, SOUND_GAIN);		break;	case _AUDC3 + _POKEY2:		AUDC[CHAN3 + CHIP2] = byte;		Update_pokey_sound(_AUDC3, byte, 1, SOUND_GAIN);		break;	case _AUDC4 + _POKEY2:		AUDC[CHAN4 + CHIP2] = byte;		Update_pokey_sound(_AUDC4, byte, 1, SOUND_GAIN);		break;	case _AUDCTL + _POKEY2:		AUDCTL[1] = byte;		/* determine the base multiplier for the 'div by n' calculations */		if (byte & CLOCK_15)			Base_mult[1] = DIV_15;		else			Base_mult[1] = DIV_64;		Update_pokey_sound(_AUDCTL, byte, 1, SOUND_GAIN);		break;	case _AUDF1 + _POKEY2:		AUDF[CHAN1 + CHIP2] = byte;		Update_pokey_sound(_AUDF1, byte, 1, SOUND_GAIN);		break;	case _AUDF2 + _POKEY2:		AUDF[CHAN2 + CHIP2] = byte;		Update_pokey_sound(_AUDF2, byte, 1, SOUND_GAIN);		break;	case _AUDF3 + _POKEY2:		AUDF[CHAN3 + CHIP2] = byte;		Update_pokey_sound(_AUDF3, byte, 1, SOUND_GAIN);		break;	case _AUDF4 + _POKEY2:		AUDF[CHAN4 + CHIP2] = byte;		Update_pokey_sound(_AUDF4, byte, 1, SOUND_GAIN);		break;	case _STIMER + _POKEY2:		Update_pokey_sound(_STIMER, byte, 1, SOUND_GAIN);		break;#endif	default:		break;	}}static void POKEY_Initialise(void){	int i;	ULONG reg;	for (i = 0; i < (MAXPOKEYS * 4); i++) {		AUDC[i] = 0;		AUDF[i] = 0;	}	for (i = 0; i < MAXPOKEYS; i++) {		AUDCTL[i] = 0;		Base_mult[i] = DIV_64;	}	/* initialise poly9_lookup */	reg = 0x1ff;	for (i = 0; i < 511; i++) {		reg = ((((reg >> 5) ^ reg) & 1) << 8) + (reg >> 1);		poly9_lookup[i] = (UBYTE) reg;	}	/* initialise poly17_lookup */	reg = 0x1ffff;	for (i = 0; i < 16385; i++) {		reg = ((((reg >> 5) ^ reg) & 0xff) << 9) + (reg >> 8);		poly17_lookup[i] = (UBYTE) (reg >> 1);	}	random_scanline_counter = 0;}UBYTE ASAP_GetByte(UWORD addr){	unsigned int i;	switch (addr & 0xff0f) {	case 0xd20a:		i = random_scanline_counter + (unsigned int) xpos + (unsigned int) xpos / LINE_C * DMAR;		if (AUDCTL[0] & POLY9)			return poly9_lookup[i % POLY9_SIZE];		else {			const UBYTE *ptr;			i %= POLY17_SIZE;			ptr = poly17_lookup + (i >> 3);			i &= 7;			return (UBYTE) ((ptr[0] >> i) + (ptr[1] << (8 - i)));		}	case 0xd40b:		return (UBYTE) ((unsigned int) xpos / (unsigned int) (2 * (LINE_C - DMAR)) % 156U);	default:		return dGetByte(addr);	}}void ASAP_PutByte(UWORD addr, UBYTE byte){	/* TODO: implement WSYNC */#if 0	if ((addr >> 8) == 0xd2)		POKEY_PutByte(addr, byte);	else if ((addr & 0xff0f) == 0xd40a) {		if (xpos <= WSYNC_C && xpos_limit >= WSYNC_C)			xpos = WSYNC_C;		else {			wsync_halt = TRUE;			xpos = xpos_limit;		}	}	else		dPutByte(addr, byte);#else	POKEY_PutByte(addr, byte);#endif}/* We use CIM opcode to return from a subroutine to ASAP */void ASAP_CIM(void){	xpos = xpos_limit;}static unsigned int block_rate;static unsigned int sample_format;static unsigned int sample_16bit;void ASAP_Initialize(unsigned int frequency, unsigned int audio_format, unsigned int quality){	block_rate = frequency;	sample_format = audio_format;	sample_16bit = audio_format == AUDIO_FORMAT_U8 ? 0 : 1;	enable_stereo = 5; /* force Pokey_sound_init() in ASAP_PlaySong() */	POKEY_Initialise();	if (quality == 0)		enable_new_pokey = FALSE;	else {		Pokey_set_mzquality(quality - 1);		enable_new_pokey = TRUE;	}}static char sap_type;static UWORD sap_player;static UWORD sap_music;static UWORD sap_init;static unsigned int sap_stereo;static unsigned int sap_songs;static unsigned int sap_defsong;static unsigned int sap_fastplay;/* This array maps subsong numbers to track positions for MPT and RMT formats. */static UBYTE song_pos[128];static unsigned int tmc_per_frame;static unsigned int tmc_per_frame_counter;static unsigned int blockclocks;static unsigned int blockclocks_per_player;static const unsigned int perframe2fastplay[] = { 312U, 312U / 2U, 312U / 3U, 312U / 4U };static int load_native(const unsigned char *module, unsigned int module_len,                       const unsigned char *player, char type){	UWORD player_last_byte;	int block_len;	if (module[0] != 0xff || module[1] != 0xff)		return FALSE;	sap_player = player[2] + (player[3] << 8);	player_last_byte = player[4] + (player[5] << 8);	sap_music = module[2] + (module[3] << 8);	if (sap_music <= player_last_byte)		return FALSE;	block_len = module[4] + (module[5] << 8) + 1 - sap_music;	if ((unsigned int) (6 + block_len) != module_len) {		UWORD info_addr;		int info_len;		if (type != 'r' || (unsigned int) (11 + block_len) > module_len)			return FALSE;		/* allow optional info for Raster Music Tracker */		info_addr = module[6 + block_len] + (module[7 + block_len] << 8);		if (info_addr != sap_music + block_len)			return FALSE;		info_len = module[8 + block_len] + (module[9 + block_len] << 8) + 1 - info_addr;		if ((unsigned int) (10 + block_len + info_len) != module_len)			return FALSE;	}	memcpy(memory + sap_music, module + 6, block_len);	memcpy(memory + sap_player, player + 6, player_last_byte + 1 - sap_player);	sap_type = type;	return TRUE;}static int load_cmc(const unsigned char *module, unsigned int module_len, int cmr){	int pos;	if (module_len < 0x300)		return FALSE;	if (!load_native(module, module_len, cmc_obx, 'C'))		return FALSE;	if (cmr)		memcpy(memory + 0x500 + CMR_BASS_TABLE_OFFSET, cmr_bass_table, sizeof(cmr_bass_table));	/* auto-detect number of subsongs */	pos = 0x54;	while (--pos >= 0) {		if (module[0x206 + pos] < 0xfe		 || module[0x25b + pos] < 0xfe		 || module[0x2b0 + pos] < 0xfe)			break;	}	while (--pos >= 0) {		if (module[0x206 + pos] == 0x8f || module[0x206 + pos] == 0xef)			sap_songs++;	}	return TRUE;}static int load_mpt(const unsigned char *module, unsigned int module_len){	unsigned int i;	unsigned int song_len;	/* seen[i] == TRUE if the track position i is already processed */	UBYTE seen[256];	if (module_len < 0x1d0)		return FALSE;	if (!load_native(module, module_len, mpt_obx, 'm'))		return FALSE;	/* do not auto-detect number of subsongs if the address	   of the first track is non-standard */	if (module[0x1c6] + (module[0x1ca] << 8) != sap_music + 0x1ca) {		song_pos[0] = 0;		return TRUE;	}	/* Calculate the length of the first track. Address of the second track minus	   address of the first track equals the length of the first track in bytes.	   Divide by two to get number of track positions. */	song_len = (module[0x1c7] + (module[0x1cb] << 8) - sap_music - 0x1ca) >> 1;	if (song_len > 0xfe)		return FALSE;	memset(seen, FALSE, sizeof(seen));	sap_songs = 0;	for (i = 0; i < song_len; i++) {		unsigned int j;		UBYTE c;		if (seen[i])			continue;		j = i;		/* follow jump commands until a pattern or a stop command is found */		do {			seen[j] = TRUE;			c = module[0x1d0 + j * 2];			if (c != 0xff)				break;			j = module[0x1d1 + j * 2];		} while (j < song_len && !seen[j]);		/* if no pattern found then this is not a subsong */		if (c >= 64)			continue;		/* found subsong */		song_pos[sap_songs++] = (UBYTE) j;		j++;		/* follow this subsong */		while (j < song_len && !seen[j]) {			seen[j] = TRUE;			c = module[0x1d0 + j * 2];			if (c < 64)				j++;			else if (c == 0xff)				j = module[0x1d1 + j * 2];			else				break;		}	}	return sap_songs != 0;}static int load_rmt(const unsigned char *module, unsigned int module_len){	unsigned int i;	UWORD song_start;	UWORD song_last_byte;	const unsigned char *song;	unsigned int song_len;	UBYTE seen[256];	if (module_len < 0x30 || module[6] != 'R' || module[7] != 'M'	 || module[8] != 'T' || module[13] != 1)		return FALSE;	switch (module[9]) {	case '4':		break;	case '8':		sap_stereo = 1;		break;	default:		return FALSE;	}	i = module[12];	if (i < 1 || i > 4)		return FALSE;	sap_fastplay = perframe2fastplay[i - 1];	if (!load_native(module, module_len, sap_stereo ? rmt8_obx : rmt4_obx, 'r'))		return FALSE;	sap_player = 0x600;	/* auto-detect number of subsongs */	song_start = module[20] + (module[21] << 8);	song_last_byte = module[4] + (module[5] << 8);	if (song_start <= sap_music || song_start >= song_last_byte)		return FALSE;	song = module + 6 + song_start - sap_music;	song_len = (song_last_byte + 1 - song_start) >> (2 + sap_stereo);	if (song_len > 0xfe)		song_len = 0xfe;	memset(seen, FALSE, sizeof(seen));	sap_songs = 0;	for (i = 0; i < song_len; i++) {		unsigned int j;		if (seen[i])			continue;		j = i;		do {			seen[j] = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -