#pragma codeseg SHARED_ extern "C" { #include #include "platform.h" #include "pc98.h" #include "planar.h" #include "decomp.h" #include "master.hpp" #include "th01/hardware/egc.h" #define graph_accesspage_1() \ outportb2(0xA6, 1); #define graph_accesspage_0() \ _AX ^= _AX; \ __asm out 0xA6, al; extern vram_word_amount_t egcrect_w; static void near egc_start_copy(void); void DEFCONV egc_copy_rect_1_to_0_16( screen_x_t left, vram_y_t top, pixel_t w, pixel_t h ) { #define vo_tmp _BX // vram_offset_t #define first_bit _CX #define stride static_cast(_BP) #define w_tmp static_cast(_AX) #define rows_remaining static_cast(_BX) #define dots static_cast(_DX) #if (GAME == 4) // TH04 wants to blit using a forward STOSW (DF = 0) __asm { cld; } #endif egc_start_copy(); egc_setrop(EGC_COMPAREREAD | EGC_WS_ROP | EGC_RL_MEMREAD | 0xF0); // Using inline assembly rather than register pseudovariables to prevent // parameters from being moved to the SI register __asm mov ax, left; __asm mov dx, top; vo_tmp = _AX; static_cast(vo_tmp) >>= 4; __asm shl bx, 1; _DX <<= 6; vo_tmp += _DX; _DX >>= 2; vo_tmp += _DX; _DI = vo_tmp; _AX &= ((BYTE_DOTS * 2) - 1); first_bit = _AX; w_tmp = ((_AX + w) >> 4); if(first_bit) { w_tmp++; } egcrect_w = w_tmp; _CX = (ROW_SIZE / 2); _CX -= w_tmp; __asm shl cx, 1; rows_remaining = h; stride = _CX; _ES = SEG_PLANE_B; do { _CX = egcrect_w; put_loop: { #if (GAME == 5) _DI |= _DI; if((!FLAGS_SIGN) && (_DI < PLANE_SIZE)) { graph_accesspage_1(); dots = peek(_ES, _DI); graph_accesspage_0(); pokew(_ES, _DI, dots); } _DI += 2; #else graph_accesspage_1(); dots = peek(_ES, _DI); graph_accesspage_0(); _AX = dots; __asm { stosw; } #endif __asm { loop put_loop; } } _DI += stride; rows_remaining--; } while(!FLAGS_SIGN); egc_off(); } #pragma codestring "\x90" #pragma option -k- static void near egc_start_copy(void) { __asm { push es push 0 pop es pushf cli // The EGC does in fact require an active GRCG in TDW mode. // (See PC-9801 Programmers' Bible, p. 456) mov al, GC_TDW out 0x7C, al // grcg_setmode() // According to MEMSYS.TXT, GRCG mode changes should always be // reflected in this memory location, for compatibility with interrupt // routines? mov byte ptr es:[0x495], al popf pop es } graph_egc_on(); outport(EGC_ACTIVEPLANEREG, 0xFFF0); egc_selectpat(); outport(EGC_MASKREG, 0xFFFF); _DX = EGC_ADDRRESSREG; outport(_DX, (_AX - _AX)); // :zunpet: outport(EGC_BITLENGTHREG, 0xF); } #pragma codestring "\x90" }