📄 scr.java
字号:
if (raw == null) { VID.Printf(Defines.PRINT_DEVELOPER, "Bad pcx file " + filename + '\n'); return 0; } // parse the PCX file pcx = new qfiles.pcx_t(raw); if (pcx.manufacturer != 0x0a || pcx.version != 5 || pcx.encoding != 1 || pcx.bits_per_pixel != 8 || pcx.xmax >= 640 || pcx.ymax >= 480) { VID.Printf(Defines.PRINT_ALL, "Bad pcx file " + filename + '\n'); return 0; } int width = pcx.xmax - pcx.xmin + 1; int height = pcx.ymax - pcx.ymin + 1; byte[] pix = new byte[width * height]; if (palette != null) { raw.position(raw.limit() - 768); raw.get(palette); } if (cin != null) { cin.pic = pix; cin.width = width; cin.height = height; } // // decode pcx // int count = 0; byte dataByte = 0; int runLength = 0; int x, y; // simple counter for buffer indexing int p = 0; for (y = 0; y < height; y++) { for (x = 0; x < width;) { dataByte = pcx.data.get(p++); if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; dataByte = pcx.data.get(p++); // write runLength pixel while (runLength-- > 0) { pix[count++] = dataByte; x++; } } else { // write one pixel pix[count++] = dataByte; x++; } } } return width * height; } /** * StopCinematic */ static void StopCinematic() { if (cin.restart_sound) { // done cl.cinematictime = 0; cin.pic = null; cin.pic_pending = null; if (cl.cinematicpalette_active) { re.CinematicSetPalette(null); cl.cinematicpalette_active = false; } if (cl.cinematic_file != null) { // free the mapped byte buffer cl.cinematic_file = null; } if (cin.hnodes1 != null) { cin.hnodes1 = null; } S.disableStreaming(); cin.restart_sound = false; } } /** * FinishCinematic * * Called when either the cinematic completes, or it is aborted */ static void FinishCinematic() { // tell the server to advance to the next map / cinematic MSG.WriteByte(cls.netchan.message, clc_stringcmd); SZ.Print(cls.netchan.message, "nextserver " + cl.servercount + '\n'); } // ========================================================================== /** * SmallestNode1 * */ private static int SmallestNode1(int numhnodes) { int best = 99999999; int bestnode = -1; for (int i = 0; i < numhnodes; i++) { if (cin.h_used[i] != 0) continue; if (cin.h_count[i] == 0) continue; if (cin.h_count[i] < best) { best = cin.h_count[i]; bestnode = i; } } if (bestnode == -1) return -1; cin.h_used[bestnode] = 1; // true return bestnode; } /** * Huff1TableInit * * Reads the 64k counts table and initializes the node trees. * */ private static void Huff1TableInit() { int[] node; byte[] counts = new byte[256]; int numhnodes; cin.hnodes1 = new int[256 * 256 * 2]; Arrays.fill(cin.hnodes1, 0); for (int prev = 0; prev < 256; prev++) { Arrays.fill(cin.h_count, 0); Arrays.fill(cin.h_used, 0); // read a row of counts cl.cinematic_file.get(counts); for (int j = 0; j < 256; j++) cin.h_count[j] = counts[j] & 0xFF; // build the nodes numhnodes = 256; int nodebase = 0 + prev * 256 * 2; int index = 0; node = cin.hnodes1; while (numhnodes != 511) { index = nodebase + (numhnodes - 256) * 2; // pick two lowest counts node[index] = SmallestNode1(numhnodes); if (node[index] == -1) break; // no more node[index + 1] = SmallestNode1(numhnodes); if (node[index + 1] == -1) break; cin.h_count[numhnodes] = cin.h_count[node[index]] + cin.h_count[node[index + 1]]; numhnodes++; } cin.numhnodes1[prev] = numhnodes - 1; } } /** * Huff1Decompress * */ private static byte[] Huff1Decompress(byte[] in, int size) { // get decompressed count int count = (in[0] & 0xFF) | ((in[1] & 0xFF)<< 8) | ((in[2] & 0xFF) << 16) | ((in[3] & 0xFF) << 24); // used as index for in[]; int input = 4; byte[] out = new byte[count]; // used as index for out[]; int out_p = 0; // read bits int hnodesbase = -256 * 2; // nodes 0-255 aren't stored int index = hnodesbase; int[] hnodes = cin.hnodes1; int nodenum = cin.numhnodes1[0]; int inbyte; while (count != 0) { inbyte = in[input++] & 0xFF; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; if (nodenum < 256) { index = hnodesbase + (nodenum << 9); out[out_p++] = (byte) nodenum; if (--count == 0) break; nodenum = cin.numhnodes1[nodenum]; } nodenum = hnodes[index + nodenum * 2 + (inbyte & 1)]; inbyte >>= 1; } if (input != size && input != size + 1) { Com.Printf("Decompression overread by " + (input - size)); } return out; } private static byte[] compressed = new byte[0x20000]; /** * ReadNextFrame */ static byte[] ReadNextFrame() { ByteBuffer file = cl.cinematic_file; // read the next frame int command = file.getInt(); if (command == 2) { // last frame marker return null; } if (command == 1) { // read palette file.get(cl.cinematicpalette); // dubious.... exposes an edge case cl.cinematicpalette_active = false; } // decompress the next frame int size = file.getInt(); if (size > compressed.length || size < 1) Com.Error(ERR_DROP, "Bad compressed frame size:" + size); file.get(compressed, 0, size); // read sound int start = cl.cinematicframe * cin.s_rate / 14; int end = (cl.cinematicframe + 1) * cin.s_rate / 14; int count = end - start; S.RawSamples(count, cin.s_rate, cin.s_width, cin.s_channels, file.slice()); // skip the sound samples file.position(file.position() + count * cin.s_width * cin.s_channels); byte[] pic = Huff1Decompress(compressed, size); cl.cinematicframe++; return pic; } /** * RunCinematic */ static void RunCinematic() { if (cl.cinematictime <= 0) { StopCinematic(); return; } if (cl.cinematicframe == -1) { // static image return; } if (cls.key_dest != key_game) { // pause if menu or console is up cl.cinematictime = cls.realtime - cl.cinematicframe * 1000 / 14; return; } int frame = (int) ((cls.realtime - cl.cinematictime) * 14.0f / 1000); if (frame <= cl.cinematicframe) return; if (frame > cl.cinematicframe + 1) { Com.Println("Dropped frame: " + frame + " > " + (cl.cinematicframe + 1)); cl.cinematictime = cls.realtime - cl.cinematicframe * 1000 / 14; } cin.pic = cin.pic_pending; cin.pic_pending = ReadNextFrame(); if (cin.pic_pending == null) { StopCinematic(); FinishCinematic(); // hack to get the black screen behind loading cl.cinematictime = 1; BeginLoadingPlaque(); cl.cinematictime = 0; return; } } /** * DrawCinematic * * Returns true if a cinematic is active, meaning the view rendering should * be skipped. */ static boolean DrawCinematic() { if (cl.cinematictime <= 0) { return false; } if (cls.key_dest == key_menu) { // blank screen and pause if menu is up Globals.re.CinematicSetPalette(null); cl.cinematicpalette_active = false; return true; } if (!cl.cinematicpalette_active) { re.CinematicSetPalette(cl.cinematicpalette); cl.cinematicpalette_active = true; } if (cin.pic == null) return true; Globals.re.DrawStretchRaw(0, 0, viddef.width, viddef.height, cin.width, cin.height, cin.pic); return true; } /** * PlayCinematic */ static void PlayCinematic(String arg) { // make sure CD isn't playing music //CDAudio.Stop(); cl.cinematicframe = 0; if (arg.endsWith(".pcx")) { // static pcx image String name = "pics/" + arg; int size = LoadPCX(name, cl.cinematicpalette, cin); cl.cinematicframe = -1; cl.cinematictime = 1; EndLoadingPlaque(); cls.state = ca_active; if (size == 0 || cin.pic == null) { Com.Println(name + " not found."); cl.cinematictime = 0; } return; } String name = "video/" + arg; cl.cinematic_file = FS.LoadMappedFile(name); if (cl.cinematic_file == null) { //Com.Error(ERR_DROP, "Cinematic " + name + " not found.\n"); FinishCinematic(); // done cl.cinematictime = 0; return; } EndLoadingPlaque(); cls.state = ca_active; cl.cinematic_file.order(ByteOrder.LITTLE_ENDIAN); ByteBuffer file = cl.cinematic_file; cin.width = file.getInt(); cin.height = file.getInt(); cin.s_rate = file.getInt(); cin.s_width = file.getInt(); cin.s_channels = file.getInt(); Huff1TableInit(); cin.restart_sound = true; cl.cinematicframe = 0; cin.pic = ReadNextFrame(); cl.cinematictime = Timer.Milliseconds(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -