extern "C" { #include #include #include #include #include "ReC98.h" #include "master.hpp" #include "th01/v_colors.hpp" #include "th01/math/clamp.hpp" #include "th01/hardware/egc.h" #include "th01/hardware/vsync.h" #include "th01/hardware/graph.h" #include "th01/hardware/palette.h" #undef grcg_off #define grcg_off() outportb(0x7C, 0); extern page_t page_accessed; /// VRAM plane "structures" /// ----------------------- #define Planes_declare(var) \ dots8_t far *var##_B = reinterpret_cast(SEG_PLANE_B); \ dots8_t far *var##_R = reinterpret_cast(SEG_PLANE_R); \ dots8_t far *var##_G = reinterpret_cast(SEG_PLANE_G); \ dots8_t far *var##_E = reinterpret_cast(SEG_PLANE_E); #define Planes_next_row(var) \ var##_B += ROW_SIZE; \ var##_R += ROW_SIZE; \ var##_G += ROW_SIZE; \ var##_E += ROW_SIZE; #define Planes_offset(var, x, y) \ var##_B += vram_offset_divmul(x, y); \ var##_R += vram_offset_divmul(x, y); \ var##_G += vram_offset_divmul(x, y); \ var##_E += vram_offset_divmul(x, y); #define PlanarRow_declare(var) \ dots8_t var##_B[ROW_SIZE]; \ dots8_t var##_R[ROW_SIZE]; \ dots8_t var##_G[ROW_SIZE]; \ dots8_t var##_E[ROW_SIZE]; \ #define PlanarRow_blit(dst, src, bytes) \ memcpy(dst##_B, src##_B, bytes); \ memcpy(dst##_R, src##_R, bytes); \ memcpy(dst##_G, src##_G, bytes); \ memcpy(dst##_E, src##_E, bytes); /// ----------------------- /// Clipping /// -------- #define fix_order(low, high) \ if(low > high) { \ order_tmp = low; \ low = high; \ high = order_tmp; \ } #define clip_min(low, high, minimum) \ if(low < minimum) { \ if(high < minimum) { \ return; \ } \ low = minimum; \ } #define clip_max(low, high, maximum) \ if(high > maximum) { \ if(low > maximum) { \ return; \ } \ high = maximum; \ } #define clip_x(left, right) \ clip_min(left, right, 0); \ clip_max(left, right, (RES_X - 1)); #define clip_y(top, bottom) \ clip_min(top, bottom, 0); \ clip_max(top, bottom, (RES_Y - 1)); /// -------- /// BIOS /// ---- inline void graph_access_and_show_0() { graph_accesspage_func(0); graph_showpage_func(0); } inline void cgrom_code_and_grcg_off() { outportb(0x68, 0xA); // CG ROM code access grcg_off(); } inline void z_graph_400line() { REGS regs; z_graph_hide(); // 640x400 regs.h.ah = 0x42; regs.h.ch = 0xC0; int86(0x18, ®s, ®s); // 16-color, analog mode outportb(0x6A, 1); } inline void z_graph_access_and_show_0() { graph_access_and_show_0(); cgrom_code_and_grcg_off(); z_graph_show(); } void z_graph_init() { z_graph_400line(); z_palette_set_all_show(z_Palettes); graph_access_and_show_0(); z_graph_clear_0(); cgrom_code_and_grcg_off(); z_graph_show(); } void graph_400line_access_and_show_0() { z_graph_400line(); z_graph_access_and_show_0(); } void z_graph_exit() { z_palette_black(); z_graph_clear_0(); graph_access_and_show_0(); z_graph_show(); cgrom_code_and_grcg_off(); } void z_graph_show() { REGS regs; regs.h.ah = 0x40; int86(0x18, ®s, ®s); } void z_graph_hide() { REGS regs; regs.h.ah = 0x41; int86(0x18, ®s, ®s); } /// ---- /// Page flipping /// ------------- void graph_showpage_func(page_t page) { outportb(0xA4, page); } void graph_accesspage_func(int page) { page_accessed = page; outportb(0xA6, page); } /// ------------- /// Hardware /// -------- void z_palette_show_single(int col, int r, int g, int b) { outportb(0xA8, col); outportb(0xAA, g); outportb(0xAC, r); outportb(0xAE, b); } #define grcg_setcolor(mode, col) \ outportb(0x7C, mode); \ outportb(0x7E, (col & 1) ? 0xFF : 0x00); \ outportb(0x7E, (col & 2) ? 0xFF : 0x00); \ outportb(0x7E, (col & 4) ? 0xFF : 0x00); \ outportb(0x7E, (col & 8) ? 0xFF : 0x00); void grcg_setcolor_rmw(int col) { grcg_setcolor(0xC0, col); } void grcg_setcolor_tcr(int col) { grcg_setcolor(0x80, col); } void grcg_off_func(void) { grcg_off(); } /// -------- /// Palette /// ------- void z_palette_set_all_show(const Palette4& pal) { for(int i = 0; i < COLOR_COUNT; i++) { z_palette_set_show(i, pal[i].c.r, pal[i].c.g, pal[i].c.b); } } void z_palette_set_show(int col, int r, int g, int b) { r = clamp_min(clamp_max(r, RGB4::max()), 0); g = clamp_min(clamp_max(g, RGB4::max()), 0); b = clamp_min(clamp_max(b, RGB4::max()), 0); z_Palettes[col].c.r = r; z_Palettes[col].c.g = g; z_Palettes[col].c.b = b; z_palette_show_single(col, r, g, b); } /// ------- /// Whole-page functions /// -------------------- void z_graph_clear() { dots8_t far *plane = reinterpret_cast(SEG_PLANE_B); grcg_setcolor_rmw(0); memset(plane, 0xFF, PLANE_SIZE); grcg_off_func(); } void z_graph_clear_0(void) { // Yes, page 2, twice. Which effectively is the same as page 0... at least // according to any real hardware and emulator tests I could come up with. graph_accesspage_func(2); z_graph_clear(); graph_accesspage_func(2); z_graph_clear(); } void z_graph_clear_col(uint4_t col) { dots8_t far *plane = reinterpret_cast(SEG_PLANE_B); grcg_setcolor_rmw(col); memset(plane, 0xFF, PLANE_SIZE); grcg_off_func(); } void graph_copy_accessed_page_to_other(void) { PlanarRow_declare(tmp); Planes_declare(p); page_t page_front = (page_accessed ^ 1); for(screen_y_t y = 0; y < RES_Y; y++) { PlanarRow_blit(tmp, p, ROW_SIZE); graph_accesspage(page_front); PlanarRow_blit(p, tmp, ROW_SIZE); graph_accesspage(page_accessed); Planes_next_row(p); } } /// -------------------- /// Palette fades /// ------------- #define FADE_DELAY 10 #define fade_loop(pal, per_comp) \ for(int i = 0; i < pal.range(); i++) { \ z_vsync_wait(); \ for(int col = 0; col < COLOR_COUNT; col++) { \ for(int comp = 0; comp < COMPONENT_COUNT; comp++) { \ per_comp; \ } \ z_palette_show_single_col(col, pal[col]); \ } \ delay(FADE_DELAY); \ } void z_palette_black(void) { for(int col = 0; col < COLOR_COUNT; col++) { z_palette_show_single(col, 0, 0, 0); } } void z_palette_black_in(void) { Palette4 fadepal; memset(&fadepal, 0, sizeof(Palette4)); fade_loop(fadepal, if(fadepal[col].v[comp] < z_Palettes[col].v[comp]) { fadepal[col].v[comp]++; } ); } void z_palette_black_out(void) { Palette4 fadepal; memcpy(&fadepal, &z_Palettes, sizeof(Palette4)); fade_loop(fadepal, if(fadepal[col].v[comp] > fadepal[0].min()) { fadepal[col].v[comp]--; } ); } void z_palette_white(void) { for(int col = 0; col < COLOR_COUNT; col++) { z_palette_show_single(col, RGB4::max(), RGB4::max(), RGB4::max()); } } void z_palette_white_in(void) { Palette4 fadepal; memset(&fadepal, fadepal[0].max(), sizeof(Palette4)); fade_loop(fadepal, if(fadepal[col].v[comp] > z_Palettes[col].v[comp]) { fadepal[col].v[comp]--; } ); } void z_palette_white_out(void) { Palette4 fadepal; memcpy(&fadepal, &z_Palettes, sizeof(Palette4)); fade_loop(fadepal, if(fadepal[col].v[comp] < fadepal[0].max()) { fadepal[col].v[comp]++; } ); } void z_palette_show(void) { for(int i = 0; i < COLOR_COUNT; i++) { z_palette_show_single_col(i, z_Palettes[i]); } } /// ------------- /// Points /// ------ #define VRAM_SBYTE(plane, offset) \ *reinterpret_cast(MK_FP(SEG_PLANE_##plane, offset)) void z_grcg_pset(screen_x_t x, vram_y_t y, int col) { grcg_setcolor_rmw(col); VRAM_SBYTE(B, vram_offset_mulshift(x, y)) = (0x80 >> (x & (BYTE_DOTS - 1))); grcg_off_func(); } int z_graph_readdot(screen_x_t x, vram_y_t y) { int ret; vram_offset_t vram_offset = vram_offset_mulshift(x, y); sdots16_t mask = (0x80 >> (x & (BYTE_DOTS - 1))); #define test(plane, vram_offset, mask, bit) \ if(VRAM_SBYTE(plane, vram_offset) & mask) { \ ret |= bit; \ } ret = 0; test(B, vram_offset, mask, 1); test(R, vram_offset, mask, 2); test(G, vram_offset, mask, 4); test(E, vram_offset, mask, 8); return ret; #undef test } /// ------ /// Restorable line drawing /// ----------------------- // Never read from, so it's supposedly only there for debugging purposes? extern screen_point_t graph_r_last_line_end; // `true` copies the pixels to be drawn from the same position on page 1, thus // restoring them with the background image. `false` (the default) draws them // regularly in the given [col]. extern bool graph_r_unput; // Not used for purely horizontal lines. extern dots16_t graph_r_pattern; void graph_r_hline(screen_x_t left, screen_x_t right, vram_y_t y, int col) { vram_byte_amount_t x; vram_byte_amount_t full_bytes_to_put; int order_tmp; dots8_t left_pixels; dots8_t right_pixels; dots8_t *vram_row; fix_order(left, right); clip_x(left, right); graph_r_last_line_end.x = right; graph_r_last_line_end.y = y; vram_row = (dots8_t *)(MK_FP(SEG_PLANE_B, vram_offset_muldiv(left, y))); full_bytes_to_put = (right / BYTE_DOTS) - (left / BYTE_DOTS); left_pixels = 0xFF >> (left & (BYTE_DOTS - 1)); right_pixels = 0xFF << ((BYTE_DOTS - 1) - (right & (BYTE_DOTS - 1))); if(!graph_r_unput) { grcg_setcolor_rmw(col); } if(graph_r_unput) { egc_copy_rect_1_to_0_16(left, y, RES_X - left, 1); } else { if(full_bytes_to_put == 0) { vram_row[0] = (left_pixels & right_pixels); } else { vram_row[0] = left_pixels; for(x = 1; x < full_bytes_to_put; x++) { vram_row[x] = 0xFF; } vram_row[full_bytes_to_put] = right_pixels; } } if(!graph_r_unput) { grcg_off_func(); } } void graph_r_vline(screen_x_t x, vram_y_t top, vram_y_t bottom, int col) { vram_y_t y; int order_tmp; dots16_t pattern; vram_offset_t vram_row_offset; fix_order(top, bottom); clip_y(top, bottom); graph_r_last_line_end.x = x; graph_r_last_line_end.y = bottom; if(graph_r_unput) { egc_copy_rect_1_to_0_16( x, top, (sizeof(pattern) * BYTE_DOTS), (bottom - top) ); return; } vram_row_offset = vram_offset_shift(x, top); pattern = graph_r_pattern >> (x & (BYTE_DOTS - 1)); pattern |= graph_r_pattern << (16 - (x & (BYTE_DOTS - 1))); grcg_setcolor_rmw(col); for(y = top; y <= bottom; y++) { grcg_put(vram_row_offset, pattern, 16); vram_row_offset += ROW_SIZE; } grcg_off_func(); } void graph_r_line_unput( screen_x_t left, vram_y_t top, screen_x_t right, vram_y_t bottom ) { graph_r_unput = true; graph_r_line(left, top, right, bottom, V_WHITE); graph_r_unput = false; } void graph_r_line_patterned( screen_x_t left, vram_y_t top, screen_x_t right, vram_y_t bottom, int col, dots16_t pattern ) { graph_r_pattern = pattern; graph_r_line(left, top, right, bottom, col); graph_r_pattern = 0x80; } void graph_r_line( screen_x_t left, vram_y_t top, screen_x_t right, vram_y_t bottom, int col ) { register vram_offset_t vram_offset; int i; screen_x_t x_cur; vram_y_t y_cur; pixel_t w, h; int error; int y_direction; int order_tmp; vram_x_t x_vram; vram_y_t y_vram; dots16_t pixels; Planar page1; #define slope_x ((bottom - top) / (right - left)) #define slope_y ((right - left) / (bottom - top)) #define lerp(m, x) static_cast(m * static_cast(x)) #define clip_lerp_min(low, high, lerp_point, slope, minimum) \ if(low < minimum) { \ if(high < minimum) { \ return; \ } \ lerp_point += lerp(slope, (minimum - low)); \ low = minimum; \ } #define clip_lerp_max(low, high, lerp_point, slope, maximum) \ if(high > maximum) { \ if(low > maximum) { \ return; \ } \ lerp_point -= lerp(slope, (high - maximum)); \ high = maximum; \ } #define restore_at(bit_count) \ graph_accesspage_func(1); VRAM_SNAP_PLANAR(page1, vram_offset, 32); \ graph_accesspage_func(0); VRAM_PUT_PLANAR(vram_offset, page1, 32); #define plot_loop(\ step_var, step_len, step_increment, \ plotted_var, plotted_len, plotted_increment \ ) \ error = (step_len >> 1); \ for(i = 0; i <= step_len; i++) { \ /* Advanced past the VRAM cursor? */ \ if((x_cur >> 3) != x_vram || (y_vram != y_cur)) { \ vram_offset = (y_vram * ROW_SIZE) + x_vram; \ if(!graph_r_unput) { \ grcg_put(vram_offset, pixels, 16); \ pixels = 0; \ } else { \ vram_offset--; \ restore_at(vram_offset); \ } \ y_vram = y_cur; \ x_vram = (x_cur >> 3); \ } \ pixels |= (graph_r_pattern >> (x_cur & (BYTE_DOTS - 1))); \ pixels |= (graph_r_pattern << (16 - (x_cur & (BYTE_DOTS - 1)))); \ error -= plotted_len; \ step_var += step_increment; \ if(error < 0) { \ error += step_len; \ plotted_var += plotted_increment; \ } \ } \ if(graph_r_unput) { \ goto restore_last; \ } \ goto end; if(!graph_r_unput && (left == right)) { graph_r_vline(left, top, bottom, col); return; } if(!graph_r_unput && (top == bottom)) { graph_r_hline(left, right, top, col); return; } if(left > right) { order_tmp = left; left = right; right = order_tmp; order_tmp = top; top = bottom; bottom = order_tmp; } clip_lerp_min(left, right, top, slope_x, 0); clip_lerp_max(left, right, bottom, slope_x, (RES_X - 1)); clip_lerp_min(top, bottom, left, slope_y, 0); clip_lerp_max(top, bottom, right, slope_y, (RES_Y - 1)); if(bottom < 0) { right += lerp(slope_y, 0 - bottom); bottom = 0; } if(top > (RES_Y - 1)) { left -= lerp(slope_y, top - (RES_Y - 1)); top = (RES_Y - 1); } graph_r_last_line_end.x = right; graph_r_last_line_end.y = bottom; x_cur = left; y_cur = top; y_direction = (top < bottom) ? 1 : -1; w = right - left; h = (bottom - top) * y_direction; pixels = 0; x_vram = (x_cur >> 3); y_vram = y_cur; if(!graph_r_unput) { grcg_setcolor_rmw(col); } if(w > h) { plot_loop(x_cur, w, 1, y_cur, h, y_direction); } else { plot_loop(y_cur, h, y_direction, x_cur, w, 1); } restore_last: vram_offset = vram_offset_shift(x_cur, y_cur) - 1; restore_at(vram_offset); end: if(!graph_r_unput) { grcg_off_func(); } #undef plot_loop #undef restore_at #undef clip_lerp_min #undef clip_lerp_max #undef slope } /// ----------------------- void z_grcg_boxfill( screen_x_t left, vram_y_t top, screen_x_t right, vram_y_t bottom, int col ) { vram_byte_amount_t x; vram_y_t y; vram_byte_amount_t full_bytes_to_put; int order_tmp; dots8_t left_pixels; dots8_t right_pixels; dots8_t *vram_row; fix_order(left, right); fix_order(top, bottom); clip_x(left, right); clip_y(top, bottom); grcg_setcolor_rmw(col); vram_row = (dots8_t *)(MK_FP(SEG_PLANE_B, vram_offset_mulshift(left, top))); for(y = top; y <= bottom; y++) { full_bytes_to_put = (right >> 3) - (left >> 3); left_pixels = 0xFF >> (left & (BYTE_DOTS - 1)); right_pixels = 0xFF << ((BYTE_DOTS - 1) - (right & (BYTE_DOTS - 1))); if(full_bytes_to_put == 0) { vram_row[0] = (left_pixels & right_pixels); } else { vram_row[0] = left_pixels; for(x = 1; x < full_bytes_to_put; x++) { vram_row[x] = 0xFF; } vram_row[full_bytes_to_put] = right_pixels; } vram_row += ROW_SIZE; } grcg_off_func(); } void graph_r_box( screen_x_t left, vram_y_t top, screen_x_t right, vram_y_t bottom, int col ) { graph_r_hline(left, right, top, col); graph_r_vline(left, top, bottom, col); graph_r_vline(right, top, bottom, col); graph_r_hline(left, right, bottom, col); } inline int fx_weight_from(int col_and_fx) { return ((col_and_fx / 0x10) % 4); } inline pixel_t fx_spacing_from(int col_and_fx) { return ((col_and_fx / 0x40) % 8); } pixel_t text_extent_fx(int col_and_fx, const unsigned char *str) { register pixel_t ret = 0; register pixel_t spacing = fx_spacing_from(col_and_fx); while(*str) { if(_ismbblead(str[0])) { uint16_t codepoint = ((char)str[0] << 8) + str[0]; str++; str++; if(codepoint < 0x8540) { ret += GLYPH_FULL_W; } else if(codepoint > 0x869E) { ret += GLYPH_FULL_W; } else { ret += GLYPH_HALF_W; } } else { ret += GLYPH_HALF_W; str++; } ret += spacing; } return ret - spacing; } #include "th01/hardware/grppsafx.cpp" void graph_putsa_fx( screen_x_t left, vram_y_t top, int16_t col_and_fx, const unsigned char *str ) { register screen_x_t x = left; uint16_t codepoint; dots_t(GLYPH_FULL_W) glyph_row; dots8_t far *vram; int fullwidth; int first_bit; int weight = fx_weight_from(col_and_fx); pixel_t spacing = fx_spacing_from(col_and_fx); int clear_bg = (col_and_fx & FX_CLEAR_BG); int underline = (col_and_fx & FX_UNDERLINE); int reverse = (col_and_fx & FX_REVERSE); pixel_t w; pixel_t line; dot_rect_t(GLYPH_FULL_W, GLYPH_H) glyph; register dots_t(GLYPH_FULL_W) glyph_row_tmp; if(clear_bg) { w = text_extent_fx(col_and_fx, str); if(underline) { z_grcg_boxfill(x, top, (x + w - 1), (top + GLYPH_H + 1), 0); graph_r_hline(x, (x + w - 1), (top + GLYPH_H + 1), V_WHITE); } else { z_grcg_boxfill(x, top, (x + w - 1), (top + GLYPH_H - 1), 0); } } else if(underline) { w = text_extent_fx(col_and_fx, str); graph_r_hline(x, (x + w - 1), (top + GLYPH_H + 1), V_WHITE); } grcg_setcolor_rmw(col_and_fx); outportb(0x68, 0xB); // CG ROM dot access while(str[0]) { set_vram_ptr(vram, first_bit, x, top); get_glyph(glyph, codepoint, fullwidth, str, x, line); for(line = 0; line < GLYPH_H; line++) { apply_weight(glyph_row, glyph[line], glyph_row_tmp, weight); if(reverse) { if(fullwidth) { glyph_row ^= 0xFFFF; } else { glyph_row ^= 0xFF00; } } put_row_and_advance(vram, glyph_row, first_bit); } advance_left(x, fullwidth, spacing); } outportb(0x68, 0xA); // CG ROM code access grcg_off_func(); } void graph_copy_byterect_from_accessed_page_to_other( screen_x_t left, vram_y_t top, screen_x_t right, vram_y_t bottom ) { pixel_t w = (right - left) / BYTE_DOTS; pixel_t h = (bottom - top); Planes_declare(p); page_t page_front = page_accessed ^ 1; pixel_t row; PlanarRow_declare(tmp); Planes_offset(p, left, top); for(row = 0; row < h; row++) { PlanarRow_blit(tmp, p, w); graph_accesspage(page_front); PlanarRow_blit(p, tmp, w); graph_accesspage(page_accessed); Planes_next_row(p); } } void graph_move_byterect_interpage( screen_x_t src_left, vram_y_t src_top, screen_x_t src_right, vram_y_t src_bottom, screen_x_t dst_left, vram_y_t dst_top, int src, int dst ) { pixel_t w = (src_right - src_left) / BYTE_DOTS; pixel_t h = (src_bottom - src_top); Planes_declare(src); Planes_declare(dst); pixel_t row; PlanarRow_declare(tmp); Planes_offset(src, src_left, src_top); Planes_offset(dst, dst_left, dst_top); for(row = 0; row < h; row++) { PlanarRow_blit(tmp, src, w); graph_accesspage(dst); PlanarRow_blit(dst, tmp, w); graph_accesspage(src); Planes_next_row(src); Planes_next_row(dst); } graph_accesspage(page_accessed); } void z_palette_fade_from( uint4_t from_r, uint4_t from_g, uint4_t from_b, int keep[COLOR_COUNT], unsigned int step_ms ) { Palette4 fadepal; int i; int col; int comp; memset(&fadepal, 0x0, sizeof(fadepal)); for(i = 0; i < COLOR_COUNT; i++) { if(!keep[i]) { fadepal[i].c.r = from_r; fadepal[i].c.g = from_g; fadepal[i].c.b = from_b; } else { fadepal[i].c.r = z_Palettes[i].c.r; fadepal[i].c.g = z_Palettes[i].c.g; fadepal[i].c.b = z_Palettes[i].c.b; } } for(i = 0; i < fadepal.range(); i++) { z_vsync_wait(); for(col = 0; col < COLOR_COUNT; col++) { for(comp = 0; comp < COMPONENT_COUNT; comp++) { if(fadepal[col].v[comp] != z_Palettes[col].v[comp]) { fadepal.colors[col].v[comp] += (fadepal[col].v[comp] < z_Palettes[col].v[comp]) ? 1 : -1; } } z_palette_show_single_col(col, fadepal[col]); } delay(step_ms); } } // Resident palette // ---------------- #define RESPAL_ID "pal98 grb" struct hack { char x[sizeof(RESPAL_ID)]; }; // XXX extern const hack PAL98_GRB; // MASTER.MAN suggests that GBR ordering is some sort of standard on PC-98. // It does match the order of the hardware's palette register ports, after // all. (0AAh = green, 0ACh = red, 0AEh = blue) struct grb_t { uint4_t g, r, b; }; struct respal_t { char id[sizeof(RESPAL_ID)]; unsigned char tone; int8_t padding[5]; grb_t pal[COLOR_COUNT]; }; // ---------------- // Memory Control Block // Adapted from FreeDOS' kernel/hdr/mcb.h // -------------------- #define MCB_NORMAL 0x4d #define MCB_LAST 0x5a struct mcb_t { uint8_t m_type; // mcb type - chain or end uint16_t __seg* m_psp; // owner id via psp segment uint16_t m_size; // size of segment in paragraphs uint8_t m_fill[3]; uint8_t m_name[8]; }; respal_t __seg* z_respal_exist(void) { union REGS regs; struct SREGS sregs; const hack ID = PAL98_GRB; seg_t mcb; int i; #define MCB reinterpret_cast(mcb) /* For easy derefencing */ #define MCB_PARAS (sizeof(mcb_t) / 16) /* For segment pointer arithmetic */ // "Get list of lists" segread(&sregs); regs.h.ah = 0x52; intdosx(®s, ®s, &sregs); mcb = *reinterpret_cast(MK_FP(sregs.es, regs.w.bx - 2)); while(1) { if(MCB->m_psp != 0) { for(i = 0; i < sizeof(ID); i++) { if(reinterpret_cast(MCB + 1)->id[i] != ID.x[i]) { break; } } if(i == sizeof(ID)) { return reinterpret_cast(mcb + MCB_PARAS); } } if(MCB->m_type != MCB_NORMAL) { return 0; } mcb += MCB_PARAS + MCB->m_size; }; #undef MCB_PARAS #undef MCB } int z_respal_get_show(void) { int i; respal_t __seg *respal_seg = z_respal_exist(); if(respal_seg) { grb_t *respal = respal_seg->pal; for(i = 0; i < COLOR_COUNT; i++) { z_palette_set_show(i, respal->r, respal->g, respal->b); respal++; } return 0; } return 1; } int z_respal_set(void) { int i; respal_t __seg *respal_seg = z_respal_exist(); if(respal_seg) { grb_t *respal = respal_seg->pal; for(i = 0; i < COLOR_COUNT; i++) { respal->g = z_Palettes[i].c.g; respal->r = z_Palettes[i].c.r; respal->b = z_Palettes[i].c.b; respal++; } return 0; } return 1; } }