www.pudn.com > ngcd080s.zip > CDROM.C
/************************************** **** CDROM.C - File reading **** **************************************/ //-- Include files ----------------------------------------------------------- #include#include #include #include #include #include #include "../cdaudio/cdaudio.h" #include "../video/video.h" #include "../memory/memory.h" #include "../mc68000/68kregs.h" #include "../z80/z80intrf.h" #include "../ym2610/adpcm.h" //-- Definitions ------------------------------------------------------------- #define BUFFER_SIZE 131072 #define PRG_TYPE 0 #define FIX_TYPE 1 #define SPR_TYPE 2 #define Z80_TYPE 3 #define PAT_TYPE 4 #define PCM_TYPE 5 //-- Imported Variables ------------------------------------------------------ extern char global_error[]; extern char *neogeo_prg_memory; extern char *neogeo_spr_memory; extern char *neogeo_fix_memory; extern char *neogeo_pcm_memory; extern Registers68K regs; extern int video_mode; extern int config_scanlines; //-- Imported Functions ------------------------------------------------------ extern void extract8(char *, char *); extern unsigned int motorola_peek(int); extern void motorola_poke(int, int); extern void neogeo_fast_copy(void *, void *, int, int, int, int, int, int); extern void neogeo_fast_copy_scanlines(void *, void *, int, int, int, int, int, int); //-- Exported Functions ------------------------------------------------------ int cdrom_init(void); int cdrom_load_prg_file(char *, unsigned int); int cdrom_load_z80_file(char *, unsigned int); int cdrom_load_fix_file(char *, unsigned int); int cdrom_load_spr_file(char *, unsigned int); int cdrom_load_pcm_file(char *, unsigned int); int cdrom_load_pat_file(char *, unsigned int, unsigned int); void cdrom_load_files(void); int cdrom_process_ipl(void); void cdrom_shutdown(void); void fix_conv(unsigned char *, unsigned char *, int, unsigned char *); void spr_conv(unsigned char *, unsigned char *, int, unsigned char *); void neogeo_upload(void); void cdrom_load_title(void); void cdrom_apply_patch(short *source, int offset, int bank); //-- Private Variables ------------------------------------------------------- static char cdrom_buffer[BUFFER_SIZE]; //-- Private Function -------------------------------------------------------- static int recon_filetype(char *); //-- Exported Variables ------------------------------------------------------ int cdrom_current_drive; BITMAP *loading_pict; int img_display = 1; //-- Defines ----------------------------------------------------------------- #define min(a, b) ((a) < (b)) ? (a) : (b) //---------------------------------------------------------------------------- int cdrom_init(void) { PACKFILE *fp; int toto; fp = pack_fopen("loading.img", "rp"); pack_fread(loading_pict->line[0], 153600L, fp); pack_fclose(fp); return 1; } //---------------------------------------------------------------------------- void cdrom_shutdown(void) { } //---------------------------------------------------------------------------- int cdrom_load_prg_file(char *FileName, unsigned int Offset) { FILE *fp; char Path[16]; char *Ptr; int Readed; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, FileName); fp = fopen(Path, "rb"); if (fp==NULL) { sprintf(global_error, "Could not open %s", Path); return 0; } if (video_mode <= 0) printf("CDROM: Loading PRG: %s, %08x...\n", Path, Offset); Ptr = neogeo_prg_memory + Offset; do { Readed = fread(cdrom_buffer, 1, BUFFER_SIZE, fp); swab(cdrom_buffer, Ptr, Readed); Ptr += Readed; } while( Readed==BUFFER_SIZE ); fclose(fp); return 1; } //---------------------------------------------------------------------------- int cdrom_load_z80_file(char *FileName, unsigned int Offset) { FILE *fp; char Path[16]; char *Ptr; int Readed; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, FileName); fp = fopen(Path, "rb"); if (fp==NULL) { sprintf(global_error, "Could not open %s", Path); return 0; } if (video_mode <= 0) printf("CDROM: Loading Z80: %s, %08x...\n", Path, Offset); fread( &subcpu_memspace, 1, 65536, fp); fclose(fp); return 1; } //---------------------------------------------------------------------------- int cdrom_load_fix_file(char *FileName, unsigned int Offset) { FILE *fp; char Path[16]; char *Ptr, *Src; int Readed; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, FileName); fp = fopen(Path, "rb"); if (fp==NULL) { sprintf(global_error, "Could not open %s", Path); return 0; } if (video_mode <= 0) printf("CDROM: Loading FIX: %s, %08x...\n", Path, Offset); Ptr = neogeo_fix_memory + Offset; do { memset(cdrom_buffer, 0, BUFFER_SIZE); Readed = fread(cdrom_buffer, 1, BUFFER_SIZE, fp); Src = cdrom_buffer; fix_conv(Src, Ptr, Readed, video_fix_usage + (Offset>>5)); Ptr += Readed; Offset += Readed; } while( Readed == BUFFER_SIZE ); fclose(fp); return 1; } //---------------------------------------------------------------------------- int cdrom_load_spr_file(char *FileName, unsigned int Offset) { FILE *fp; char Path[16]; char *Ptr; int Readed; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, FileName); fp = fopen(Path, "rb"); if (fp==NULL) { sprintf(global_error, "Could not open %s", Path); return 0; } if (video_mode <= 0) printf("CDROM: Loading SPR: %s, %08x...\n", Path, Offset); Ptr = neogeo_spr_memory + Offset; do { memset(cdrom_buffer, 0, BUFFER_SIZE); Readed = fread(cdrom_buffer, 1, BUFFER_SIZE, fp); spr_conv(cdrom_buffer, Ptr, Readed, video_spr_usage + (Offset>>7)); Offset += Readed; Ptr += Readed; } while( Readed == BUFFER_SIZE ); fclose(fp); return 1; } //---------------------------------------------------------------------------- int cdrom_load_pcm_file(char *FileName, unsigned int Offset) { FILE *fp; char Path[16]; char *Ptr, *Src; int Readed; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, FileName); fp = fopen(Path, "rb"); if (fp==NULL) { sprintf(global_error, "Could not open %s", Path); return 0; } if (video_mode <= 0) printf("CDROM: Loading PCM: %s, %08x...\n", Path, Offset); Ptr = neogeo_pcm_memory + Offset; fread(Ptr, 1, 0x100000, fp); fclose(fp); return 1; } //---------------------------------------------------------------------------- int cdrom_load_pat_file(char *FileName, unsigned int Offset, unsigned int Bank) { FILE *fp; char Path[16]; char *Ptr, *Src; int Readed; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, FileName); fp = fopen(Path, "rb"); if (fp==NULL) { sprintf(global_error, "Could not open %s", Path); return 0; } if (video_mode <= 0) printf("CDROM: Loading PAT: %s, %08x...\n", Path, Offset); Readed = fread(cdrom_buffer, 1, BUFFER_SIZE, fp); swab(cdrom_buffer, cdrom_buffer, Readed); cdrom_apply_patch((short*)cdrom_buffer, Offset, Bank); fclose(fp); return 1; } //---------------------------------------------------------------------------- int cdrom_process_ipl(void) { FILE *fp; char Path[16]; char Line[32]; char FileName[16]; char Bank[4]; char Offset[8]; int FileType; int Bnk; int Off; int i, j; strcpy(Path, "X:\\"); Path[0] = cdrom_current_drive + 65; strcat(Path, "IPL.TXT"); fp = fopen(Path, "rb"); if (fp==NULL) { strcpy(global_error, "Could not open IPL.TXT!"); return 0; } while (fgets(Line, 32, fp)!=NULL) { i=0; j=0; while((Line[i] != ',')&&(Line[i]!=0)) FileName[j++] = toupper(Line[i++]); FileName[j]=0; j -= 3; if (j>0) { FileType = recon_filetype(&FileName[j]); i++; j=0; while(Line[i] != ',') Bank[j++] = Line[i++]; Bank[j]=0; i++; j=0; while(Line[i] != 0x0D) Offset[j++] = Line[i++]; Offset[j] = 0; sscanf(Bank, "%d", &Bnk); sscanf(Offset, "%08x", &Off); switch( FileType ) { case PRG_TYPE: if (!cdrom_load_prg_file(FileName, Off)) { fclose(fp); return 0; } break; case FIX_TYPE: if (!cdrom_load_fix_file(FileName, (Off>>1))) { fclose(fp); return 0; } break; case SPR_TYPE: if (!cdrom_load_spr_file(FileName, (Bnk*0x100000) + Off)) { fclose(fp); return 0; } break; case Z80_TYPE: if (!cdrom_load_z80_file(FileName, Off)) { fclose(fp); return 0; } break; case PAT_TYPE: if (!cdrom_load_pat_file(FileName, Off, Bnk)) { fclose(fp); return 0; } break; case PCM_TYPE: if (!cdrom_load_pcm_file(FileName, (Bnk*0x80000) + (Off>>1))) { fclose(fp); return 0; } break; } } } fclose(fp); return 1; } //---------------------------------------------------------------------------- int recon_filetype(char *ext) { if (strcmp(ext, "PRG")==0) return PRG_TYPE; if (strcmp(ext, "FIX")==0) return FIX_TYPE; if (strcmp(ext, "SPR")==0) return SPR_TYPE; if (strcmp(ext, "Z80")==0) return Z80_TYPE; if (strcmp(ext, "PAT")==0) return PAT_TYPE; if (strcmp(ext, "PCM")==0) return PCM_TYPE; return -1; } //---------------------------------------------------------------------------- void cdrom_load_files(void) { char Entry[32], FileName[13], Ext[4]; char *Ptr; int i, j, Bnk, Off, Type, Reliquat; sound_mute(); if (cpu_readmem24(regs.a0)==0) return; if (cdda_playing) { cdda_stop(); cdda_current_track = 0; } cpu_writemem24_dword(0x10F68C, 0x00000000); cpu_writemem24(0x10F6C3, 0x00); cpu_writemem24(0x10F6D9, 0x01); cpu_writemem24(0x10F6DB, 0x01); cpu_writemem24_dword(0x10F742, 0x00000000); cpu_writemem24_dword(0x10F746, 0x00000000); cpu_writemem24(0x10FDC2, 0x01); cpu_writemem24(0x10FDDC, 0x00); cpu_writemem24(0x10FDDD, 0x00); cpu_writemem24(0x10FE85, 0x01); cpu_writemem24(0x10FE88, 0x00); cpu_writemem24(0x10FEC4, 0x01); //video_set_txt_mode(); if (video_mode <= 0) printf("Load list at : %08x\n", regs.a0); else if (img_display == 1) { if (config_scanlines) neogeo_fast_copy_scanlines(loading_pict, screen, 0, 0, 0, 0, 320, 240); else neogeo_fast_copy(loading_pict, screen, 0, 0, 0, 0, 320, 240); } Ptr = neogeo_prg_memory + regs.a0; do { Reliquat = ((int)Ptr)&1; if (Reliquat) Ptr--; swab(Ptr, Entry, 32); i=Reliquat; // while(i<32) // printf("%02x ", (unsigned char)Ptr[i++]); // printf("\n"); while((Entry[i]!=0)&&(Entry[i]!=';')) FileName[i-Reliquat] = toupper(Entry[i++]); FileName[i-Reliquat] = 0; if (Entry[i]==';') /* 01/05/99 MSLUG2 FIX */ i += 2; i++; Bnk = Entry[i++]; if (i&1) i++; Off = motorola_peek((unsigned int)&Entry[i]); i += 4; Ptr += i; // printf(" %s %02x %08x\n", FileName, Bnk, Off); j=0; while(FileName[j] != 0x2e) j++; j++; Ext[0] = FileName[j++]; Ext[1] = FileName[j++]; Ext[2] = FileName[j]; Ext[3] = 0; Type = recon_filetype(Ext); switch( Type ) { case PRG_TYPE: cdrom_load_prg_file(FileName, Off); break; case FIX_TYPE: cdrom_load_fix_file(FileName, Off>>1); break; case SPR_TYPE: cdrom_load_spr_file(FileName, (Bnk*0x100000) + Off); break; case Z80_TYPE: cdrom_load_z80_file(FileName, Off); break; case PAT_TYPE: cdrom_load_pat_file(FileName, Off, Bnk); break; case PCM_TYPE: cdrom_load_pcm_file(FileName, (Bnk*0x80000) + (Off>>1)); break; } } while( Entry[i] != 0); // clear_keybuf(); // readkey(); // video_set_gfx_mode(); if (img_display == 1) clear(screen); } //---------------------------------------------------------------------------- void fix_conv(unsigned char *Src, unsigned char *Ptr, int Taille, unsigned char *usage_ptr) { int i; unsigned char usage; for(i=Taille;i>0;i-=32) { usage = 0; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src++; *Ptr++ = *(Src+16); usage |= *(Src+16); *Ptr++ = *(Src+24); usage |= *(Src+24); *Ptr++ = *(Src); usage |= *(Src); *Ptr++ = *(Src+8); usage |= *(Src+8); Src+=25; *usage_ptr++ = usage; } } //---------------------------------------------------------------------------- void spr_conv(unsigned char *Src1, unsigned char *Ptr, int Taille, unsigned char *usage_ptr) { unsigned char *Src2; unsigned char reference[128]; register int i; memset(reference, 0, 128); Src2 = Src1 + 64; for(i=Taille;i>0;i-=128) { extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; extract8(Src2, Ptr); Src2 += 4; Ptr += 4; extract8(Src1, Ptr); Src1 += 4; Ptr += 4; Src1 += 64; Src2 += 64; if (memcmp(reference, Ptr-128, 128)==0) *usage_ptr++ = 0; else *usage_ptr++ = 1; } } //---------------------------------------------------------------------------- void neogeo_upload(void) { int Zone; int Taille; int Banque; int Offset = 0; unsigned char *Source; unsigned char *Dest; FILE *fp; Zone = cpu_readmem24(0x10FEDA); /* fp = fopen("C:\\TMP\\UPLOAD.LOG", "at"); fprintf(fp, "%02x: %06x, %06x:%02x, %08x\n", Zone, cpu_readmem24_dword(0x10FEF8), cpu_readmem24_dword(0x10FEF4), cpu_readmem24(0x10FEDB), cpu_readmem24_dword(0x10FEFC)); fclose(fp);*/ switch( Zone&0x0F ) { case 0: // PRG Source = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF8); Dest = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF4); Taille = cpu_readmem24_dword(0x10FEFC); memcpy(Dest, Source, Taille); cpu_writemem24_dword( 0x10FEF4, cpu_readmem24_dword(0x10FEF4) + Taille ); break; case 2: // SPR Banque = cpu_readmem24(0x10FEDB); Source = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF8); Offset = cpu_readmem24_dword(0x10FEF4) + (Banque<<20); Dest = neogeo_spr_memory + Offset; Taille = cpu_readmem24_dword(0x10FEFC); do { memset(cdrom_buffer, 0, BUFFER_SIZE); swab(Source, cdrom_buffer, min(BUFFER_SIZE, Taille)); spr_conv(cdrom_buffer, Dest, min(BUFFER_SIZE, Taille), video_spr_usage + (Offset>>7)); Source += min(BUFFER_SIZE, Taille); Dest += min(BUFFER_SIZE, Taille); Offset += min(BUFFER_SIZE, Taille); Taille -= min(BUFFER_SIZE, Taille); } while(Taille!=0); // Mise à jour des valeurs Offset = cpu_readmem24_dword( 0x10FEF4 ); Banque = cpu_readmem24( 0x10FEDB ); Taille = cpu_readmem24( 0x10FEFC ); Offset += Taille; while (Offset > 0x100000 ) { Banque++; Offset -= 0x100000; } cpu_writemem24_dword( 0x10FEF4, Offset ); cpu_writemem24_word( 0x10FEDB, Banque ); break; case 1: // FIX Source = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF8); Offset = cpu_readmem24_dword(0x10FEF4)>>1; Dest = neogeo_fix_memory + Offset; Taille = cpu_readmem24_dword(0x10FEFC); do { memset(cdrom_buffer, 0, BUFFER_SIZE); swab(Source, cdrom_buffer, min(BUFFER_SIZE, Taille)); fix_conv(cdrom_buffer, Dest, min(BUFFER_SIZE, Taille), video_fix_usage + (Offset>>5)); Source += min(BUFFER_SIZE, Taille); Dest += min(BUFFER_SIZE, Taille); Offset += min(BUFFER_SIZE, Taille); Taille -= min(BUFFER_SIZE, Taille); } while(Taille!=0); Offset = cpu_readmem24_dword( 0x10FEF4 ); Taille = cpu_readmem24_dword( 0x10FEFC ); Offset += (Taille<<1); cpu_writemem24_dword( 0x10FEF4, Offset); break; case 3: // Z80 Source = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF8); Dest = subcpu_memspace + (cpu_readmem24_dword(0x10FEF4)>>1); Taille = cpu_readmem24_dword(0x10FEFC); swab(Source, Dest, Taille); cpu_writemem24_dword( 0x10FEF4, cpu_readmem24_dword(0x10FEF4) + (Taille<<1) ); break; case 5: // Z80 patch Source = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF8); cdrom_apply_patch((short*)Source, cpu_readmem24_dword(0x10FEF4), cpu_readmem24(0x10FEDB)); break; case 4: // PCM Banque = cpu_readmem24(0x10FEDB); Source = neogeo_prg_memory + cpu_readmem24_dword(0x10FEF8); Offset = (cpu_readmem24_dword(0x10FEF4)>>1) + (Banque<<19); Dest = neogeo_pcm_memory + Offset; Taille = cpu_readmem24_dword(0x10FEFC); swab( Source, Dest, Taille); // Mise à jour des valeurs Offset = cpu_readmem24_dword( 0x10FEF4 ); Banque = cpu_readmem24( 0x10FEDB ); Taille = cpu_readmem24( 0x10FEFC ); Offset += (Taille<<1); while (Offset > 0x100000 ) { Banque++; Offset -= 0x100000; } cpu_writemem24_dword( 0x10FEF4, Offset ); cpu_writemem24_word( 0x10FEDB, Banque ); break; } } //---------------------------------------------------------------------------- void cdrom_load_title(void) { static char *jue = "JUE"; static char *file = "X:\\TITLE_X.SYS"; FILE *fp; char *Ptr; int Readed; int x, y; file[9] = jue[cpu_readmem24(0x10FD83)&3]; file[0] = cdrom_current_drive + 65; fp = fopen(file, "rb"); if (fp==NULL) { clear(game_title); return; } fread(video_paletteram_pc, 1, 0x5A0, fp); swab(video_paletteram_pc, video_paletteram_pc, 0x5A0); for(Readed=0;Readed<720;Readed++) video_paletteram_pc[Readed] = video_color_lut[video_paletteram_pc[Readed]]; Ptr = neogeo_spr_memory; Readed = fread(cdrom_buffer, 1, BUFFER_SIZE, fp); spr_conv(cdrom_buffer, Ptr, Readed, video_spr_usage); fclose(fp); Readed = 0; for(y=0;y<80;y+=16) { for(x=0;x<144;x+=16) { video_draw_spr(Readed, Readed, 0, 0, x, y, 15, 16); Readed++; } } blit(video_buffer, game_title, 8, 0, 0, 0, 144, 80); scare_mouse(); blit(video_buffer, screen, 8, 0, 35, 30, 144, 80); unscare_mouse(); memset(neogeo_spr_memory, 0, 4194304); memset(neogeo_fix_memory, 0, 131072); memset(video_spr_usage, 0, 32768); memset(video_fix_usage, 0, 4096); } #define PATCH_Z80(a, b) { \ subcpu_memspace[(a)] = (b)&0xFF; \ subcpu_memspace[(a+1)] = ((b)>>8)&0xFF; \ } void cdrom_apply_patch(short *source, int offset, int bank) { int master_offset; master_offset = (((bank*1048576) + offset)/256)&0xFFFF; while(*source != 0) { PATCH_Z80( source[0], ((source[1] + master_offset)>>1) ); PATCH_Z80( source[0] + 2, (((source[2] + master_offset)>>1) - 1) ); if ((source[3])&&(source[4])) { PATCH_Z80( source[0] + 5, ((source[3] + master_offset)>>1) ); PATCH_Z80( source[0] + 7, (((source[4] + master_offset)>>1) - 1) ); } source += 5; } }