2025-02-15 08:27:17 +09:00
/*
* 86 Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus .
*
* This file is part of the 86 Box distribution .
*
* IBM PS / 55 Display Adapter II emulation .
*
* Authors : Akamaki .
*
* Copyright 2024 Akamaki .
*/
# include <stdarg.h>
# include <stdint.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <wchar.h>
# include <stdatomic.h>
# define HAVE_STDARG_H
# include <86box/86box.h>
# include <86box/device.h>
# include <86box/io.h>
# include <86box/machine.h>
# include <86box/mem.h>
# include <86box/timer.h>
# include <86box/mca.h>
# include <86box/rom.h>
# include <86box/plat.h>
# include <86box/thread.h>
# include <86box/video.h>
# include <86box/vid_ps55da2.h>
# include <86box/vid_svga.h>
# include <86box/vid_svga_render.h>
# include "cpu.h"
# define DA2_FONTROM_PATH_JPAN "roms / video / da2 / 94X1320.BIN"
# define DA2_FONTROM_PATH_HANT "roms / video / da2 / 23F2698.BIN"
# define DA2_FONTROM_SIZE 1536*1024
# define DA2_FONTROM_BASESBCS 0x98000
# define DA2_GAIJIRAM_SBCS 0x34000
# define DA2_GAIJIRAM_SBEX 0x3c000
# define DA2_INVALIDACCESS8 0xff
# define DA2_MASK_MMIO 0x1ffff
# define DA2_MASK_GRAM 0x1ffff
# define DA2_MASK_CRAM 0xfff
# define DA2_MASK_GAIJIRAM 0x3ffff
# define DA2_PIXELCLOCK 58000000.0
# define DA2_BLT_MEMSIZE 0x100
# define DA2_BLT_REGSIZE 0x40
# define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1)
# define DA2_DEBUG_BLTLOG_MAX 256*1024
# define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe
# define DA2_DEBUG_BLT_USEDRESET 0xfefefe
# define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */
//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */
//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */
# define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */
# define DA2_DCONFIG_MONTYPE_COLOR 0x0A
# define DA2_DCONFIG_MONTYPE_8515 0x0B
# define DA2_DCONFIG_MONTYPE_MONO 0x09
# define DA2_BLT_CIDLE 0
# define DA2_BLT_CFILLRECT 1
# define DA2_BLT_CFILLTILE 2
# define DA2_BLT_CCOPYF 3
# define DA2_BLT_CCOPYR 4
# define DA2_BLT_CPUTCHAR 5
# define DA2_BLT_CDONE 6
# define DA2_BLT_CLOAD 7
/* POS ID = 0xeffe : Display Adapter II, III, V */
# define DA2_POSID_H 0xef
# define DA2_POSID_L 0xfe
/*
[ Identification ]
POS ID SYS ID
EFFFh * Display Adapter ( PS / 55 Model 5571 - S0A ) [ Toledo ]
E013h * Layout Display Terminal ( PS / 55 - 5571 RPQ model ) [ LDT ]
EFFEh * Display Adapter II ( I / O 3E0 : 0 A = xx0x xxxx ) [ Atlas ]
| - FFF2h Display Adapter B2 ( I / O 3E0 : 0 A = xx1x xxxx ) ( PS / 55 Model 5530 Z - SX )
| - FDFEh Display Adapter B2 ( I / O 3E0 : 0 A = xx1x xxxx ) ( PS / 55 Model 5550 - V2 )
| - * Display Adapter III , V ( I / O 3E0 : 0 A = xx1x xxxx )
ECECh FF4Fh Display Adapter B1 ( PS / 55 Model 5531 Z - SX ) [ Atlas - KENT ]
| - * Display Adapter IV
ECCEh * Display Adapter IV
901F h * Display Adapter A2
901 Dh * Display Adapter A1 [ Atlas II ]
901 Eh * Plasma Display Adapter
EFD8h * Display Adapter / J [ Atlas - SP2 ]
[ Japanese DOS and Display Adapter compatibility ]
| POS ID | Adapter Name | K3 .31 | J4 .04 | J5 .02 | OS2 J1 .3 | Win3 |
| - - - - - - - - - - - - | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | : - - - - - : | : - - - - - : | : - - - - - : | : - - - - - - - - : | : - - - - : |
| EFFFh | Display Adapter | X | | | ? | |
| FFEDh | ? [ Atlas EVT ] | X | | | ? | |
| FFFDh | ? [ LDT EVT ] | X | | | ? | |
| EFFEh | Display Adapter II , III , V , B2 | X | X | X | X | X |
| E013h | ? [ LDT ] | X | X | X | X | |
| ECCEh | Display Adapter IV | | X | X | X | |
| ECECh | Display Adapter IV , B1 | | X | X | X | X |
| 9000 - 901F h | Display Adapter A1 , A2 | | X | X | | X |
| EFD8h | Display Adapter / J | | | X | X | X |
*/
/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */
# define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */
//#define Mon_ID3 0x10
# define FontCard 0x08 /* ? */
/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */
# define Page_One 0x06 /* 80000h 110b */
# define Page_Two 0x05 /* 100000h 101b */
# define Page_Four 0x03 /* 200000h 011b */
/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */
# define AddPage 0x08 /* ? */
//#define Mon_ID2 0x04
//#define Mon_ID1 0x02
//#define Mon_ID0 0x01
/* Monitor ID (imported from OS/2 DDK 1.2) */
//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768
//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale
//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp
//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B
/* DA2 Registers (imported from OS/2 DDK) */
# define AC_REG 0x3EE
# define AC_DMAE 0x80
# define AC_FONT_SEL 0x40
# define FONT_BANK 0x3EF
# define LS_INDEX 0x3E0
# define LS_DATA 0x3E1
# define LS_RESET 0x00
# define LS_MODE 0x02
# define LS_STATUS 0x03 /* added */
# define LS_MMIO 0x08 /* added */
# define LS_CONFIG1 0x0a
# define LS_CONFIG2 0x0b /* added */
# define LF_INDEX 0x3e2
# define LF_DATA 0x3e3
# define LF_MMIO_SEL 0x08 /* added */
# define LF_MMIO_ADDR 0x0A /* added */
# define LF_MMIO_MODE 0x0B /* added */
# define LC_INDEX 0x3E4
# define LC_DATA 0x3E5
# define LC_HORIZONTAL_TOTAL 0x00
# define LC_H_DISPLAY_ENABLE_END 0x01
# define LC_START_H_BLANKING 0x02
# define LC_END_H_BLANKING 0x03
# define LC_START_HSYNC_PULSE 0x04
# define LC_END_HSYNC_PULSE 0x05
# define LC_VERTICAL_TOTALJ 0x06
# define LC_CRTC_OVERFLOW 0x07
# define LC_PRESET_ROW_SCANJ 0x08
# define LC_MAXIMUM_SCAN_LINE 0x09
# define LC_CURSOR_ROW_START 0x0A
# define LC_CURSOR_ROW_END 0x0B
# define LC_START_ADDRESS_HIGH 0x0C
# define LC_START_ADDRESS_LOW 0x0D
# define LC_CURSOR_LOC_HIGH 0x0E
# define LC_ROW_CURSOR_LOC 0x0E
# define LC_CURSOR_LOC_LOWJ 0x0F
# define LC_COLUMN_CURSOR_LOC 0x0F
# define LC_VERTICAL_SYNC_START 0x10
# define LC_LIGHT_PEN_HIGH 0x10
# define LC_VERTICAL_SYNC_END 0x11
# define LC_LIGHT_PEN_LOW 0x11
# define LC_V_DISPLAY_ENABLE_END 0x12
# define LC_OFFSET 0x13
# define LC_UNDERLINE_LOCATION 0x14
# define LC_START_VERTICAL_BLANK 0x15
# define LC_END_VERTICAL_BLANK 0x16
# define LC_LC_MODE_CONTROL 0x17
# define LC_LINE_COMPAREJ 0x18
# define LC_START_H_DISPLAY_ENAB 0x19
# define LC_START_V_DISPLAY_ENAB 0x1A
# define LC_VIEWPORT_COMMAND 0x1B
# define LC_VIEWPORT_SELECT 0x1C
# define LC_VIEWPORT_PRIORITY 0x1D
# define LC_COMMAND 0x1E
# define LC_COMPATIBILITY 0x1F
# define LC_VIEWPORT_NUMBER 0x1F
# define LV_PORT 0x3E8
# define LV_PALETTE_0 0x00
# define LV_MODE_CONTROL 0x10
# define LV_OVERSCAN_COLOR 0x11
# define LV_COLOR_PLANE_ENAB 0x12
# define LV_PANNING 0x13
# define LV_VIEWPORT1_BG 0x14
# define LV_VIEWPORT2_BG 0x15
# define LV_VIEWPORT3_BG 0x16
# define LV_BLINK_COLOR 0x17
# define LV_BLINK_CODE 0x18
# define LV_GR_CURSOR_ROTATION 0x19
# define LV_GR_CURSOR_COLOR 0x1A
# define LV_GR_CURSOR_CONTROL 0x1B
# define LV_COMMAND 0x1C
# define LV_VP_BORDER_LINE 0x1D
# define LV_SYNC_POLARITY 0x1F
# define LV_CURSOR_CODE_0 0x20
# define LV_GRID_COLOR_0 0x34
# define LV_GRID_COLOR_1 0x35
# define LV_GRID_COLOR_2 0x36
# define LV_GRID_COLOR_3 0x37
# define LV_ATTRIBUTE_CNTL 0x38
# define LV_CURSOR_COLOR 0x3A
# define LV_CURSOR_CONTROL 0x3B
# define LV_RAS_STATUS_VIDEO 0x3C
# define LV_PAS_STATUS_CNTRL 0x3D
# define LV_IDENTIFICATION 0x3E
# define LV_OUTPUT 0x3E
# define LV_COMPATIBILITY 0x3F
# define LG_INDEX 0x3EA
# define LG_DATA 0x3EB
# define LG_SET_RESETJ 0x00
# define LG_ENABLE_SRJ 0x01
# define LG_COLOR_COMPAREJ 0x02
# define LG_DATA_ROTATION 0x03
# define LG_READ_MAP_SELECT 0x04
# define LG_MODE 0x05
# define LG_COMPLEMENT 0x06
# define LG_COLOR_DONT_CARE 0x07
# define LG_BIT_MASK_LOW 0x08
# define LG_BIT_MASK_HIGH 0x09
# define LG_MAP_MASKJ 0x0A
# define LG_COMMAND 0x0B
# define LG_SET_RESET_2 0x10
# ifndef RELEASE_BUILD
2025-02-15 11:05:16 +09:00
//#define ENABLE_DA2_LOG 1
2025-02-15 08:27:17 +09:00
# endif
# ifdef ENABLE_DA2_LOG
2025-02-15 11:05:16 +09:00
# define ENABLE_DA2_DEBUGBLT 1
2025-02-15 08:27:17 +09:00
int da2_do_log = ENABLE_DA2_LOG ;
static void
da2_log ( const char * fmt , . . . )
{
va_list ap ;
if ( da2_do_log ) {
va_start ( ap , fmt ) ;
pclog_ex ( fmt , ap ) ;
va_end ( ap ) ;
}
}
# else
# define da2_log(fmt, ...)
# endif
typedef struct da2_t
{
//mem_mapping_t vmapping;
mem_mapping_t cmapping ;
//uint8_t crtcreg;
uint8_t ioctl [ 16 ] ;
uint8_t fctl [ 32 ] ;
uint16_t crtc [ 128 ] ;
uint8_t gdcreg [ 64 ] ;
uint8_t reg3ee [ 16 ] ;
int gdcaddr ;
uint8_t attrc [ 0x40 ] ;
int attraddr , attrff ;
int attr_palette_enable ;
//uint8_t seqregs[64];
int outflipflop ;
int inflipflop ;
int iolatch ;
int ioctladdr ;
int fctladdr ;
int crtcaddr ;
uint32_t decode_mask ;
uint32_t vram_max ;
uint32_t vram_mask ;
uint32_t gdcla [ 8 ] ;
uint32_t gdcinput [ 8 ] ;
uint32_t gdcsrc [ 8 ] ;
uint32_t debug_vramold [ 8 ] ;
uint8_t dac_mask , dac_status ;
int dac_read , dac_write , dac_pos ;
int dac_r , dac_g ;
uint8_t cgastat ;
uint8_t plane_mask ;
int fb_only ;
int fast ;
uint8_t colourcompare , colournocare ;
int readmode , writemode , readplane ;
uint8_t writemask ;
uint32_t charseta , charsetb ;
uint8_t egapal [ 16 ] ;
uint32_t pallook [ 512 ] ;
PALETTE vgapal ;
int vtotal , dispend , vsyncstart , split , vblankstart ;
int hdisp , hdisp_old , htotal , hdisp_time , rowoffset ;
int lowres , interlace ;
int rowcount ;
double clock ;
uint32_t ma_latch , ca_adj ;
uint64_t dispontime , dispofftime ;
pc_timer_t timer ;
uint64_t da2const ;
int dispon ;
int hdisp_on ;
uint32_t ma , maback , ca ;
int vc ;
int sc ;
int linepos , vslines , linecountff , oddeven ;
int con , cursoron , blink , blinkconf ;
int scrollcache ;
int char_width ;
int firstline , lastline ;
int firstline_draw , lastline_draw ;
int displine ;
/* Attribute Buffer E0000-E0FFFh (4 KB) */
uint8_t * cram ;
/* (cram size - 1) >> 3 = 0xFFF */
//uint32_t cram_display_mask;
/* APA Buffer A0000-BFFFFh (128 KB) */
uint8_t * vram ;
/* addr >> 12 = xx000h */
uint8_t * changedvram ;
/* (vram size - 1) >> 3 = 0x1FFFF */
uint32_t vram_display_mask ;
//uint32_t write_bank, read_bank;
int fullchange ;
void ( * render ) ( struct da2_t * da2 ) ;
/*If set then another device is driving the monitor output and the SVGA
card should not attempt to display anything */
int override ;
/* end VGA compatible regs*/
struct
{
int enable ;
mem_mapping_t mapping ;
uint8_t ram [ 256 * 1024 ] ;
uint8_t * font ;
int charset ;
} mmio ;
struct {
int bitshift_destr ;
int raster_op ;
uint8_t payload [ DA2_BLT_MEMSIZE ] ;
int32_t reg [ DA2_BLT_REGSIZE ] ; //must be signed int
int32_t * debug_reg ; //for debug
int debug_reg_ip ; //for debug
int payload_addr ;
pc_timer_t timer ;
int64_t timerspeed ;
int exec ;
int indata ;
int32_t destaddr ;
int32_t srcaddr ;
int32_t size_x , tile_w ;
int32_t size_y ;
int16_t destpitch ;
int16_t srcpitch ;
int32_t fcolor ;
int32_t maskl , maskr ;
int x , y ;
} bitblt ;
FILE * mmdbg_fp ;
FILE * mmrdbg_fp ;
uint32_t mmdbg_vidaddr ;
uint32_t mmrdbg_vidaddr ;
uint8_t pos_regs [ 8 ] ;
svga_t * mb_vga ;
uint8_t monitorid ;
int old_pos2 ;
} da2_t ;
void da2_recalctimings ( da2_t * da2 ) ;
static void da2_mmio_gc_writeW ( uint32_t addr , uint16_t val , void * p ) ;
void da2_bitblt_exec ( void * p ) ;
void da2_updatevidselector ( da2_t * da2 ) ;
void da2_reset_ioctl ( da2_t * da2 ) ;
static void da2_reset ( void * priv ) ;
typedef union {
uint32_t d ;
uint8_t b [ 4 ] ;
} DA2_VidSeq32 ;
typedef struct {
uint32_t p8 [ 8 ] ;
} pixel32 ;
/* safety read for internal functions */
uint32_t DA2_readvram_s ( uint32_t addr , da2_t * da2 )
{
if ( addr & ~ da2 - > vram_mask ) return - 1 ;
return da2 - > vram [ addr ] ;
}
void DA2_WritePlaneDataWithBitmask ( uint32_t destaddr , const uint16_t mask , pixel32 * srcpx , da2_t * da2 )
{
uint32_t writepx [ 8 ] ;
destaddr & = 0xfffffffe ; /* align to word address to work bit shift correctly */
//da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr);
da2 - > changedvram [ ( da2 - > vram_display_mask & destaddr ) > > 12 ] = changeframecount ;
da2 - > changedvram [ ( da2 - > vram_display_mask & ( destaddr + 1 ) ) > > 12 ] = changeframecount ;
destaddr < < = 3 ;
/* read destination data with big endian order */
for ( int i = 0 ; i < 8 ; i + + )
writepx [ i ] = DA2_readvram_s ( ( destaddr + 24 ) | i , da2 )
| ( DA2_readvram_s ( ( destaddr + 16 ) | i , da2 ) < < 8 )
| ( DA2_readvram_s ( ( destaddr + 8 ) | i , da2 ) < < 16 )
| ( DA2_readvram_s ( ( destaddr + 0 ) | i , da2 ) < < 24 ) ;
DA2_VidSeq32 mask32in ; mask32in . d = ( uint32_t ) mask ;
DA2_VidSeq32 mask32 ; mask32 . d = 0 ;
mask32 . b [ 3 ] = mask32in . b [ 0 ] ;
mask32 . b [ 2 ] = mask32in . b [ 1 ] ;
mask32 . d & = 0xffff0000 ;
for ( int i = 0 ; i < 8 ; i + + )
{
if ( da2 - > bitblt . bitshift_destr > 0 )
srcpx - > p8 [ i ] < < = 16 - da2 - > bitblt . bitshift_destr ;
switch ( da2 - > bitblt . raster_op ) {
case 0x00 : /* None */
writepx [ i ] & = ~ mask32 . d ;
writepx [ i ] | = srcpx - > p8 [ i ] & mask32 . d ;
break ;
case 0x01 : /* AND */
writepx [ i ] & = srcpx - > p8 [ i ] | ~ mask32 . d ;
break ;
case 0x02 : /* OR */
writepx [ i ] | = srcpx - > p8 [ i ] & mask32 . d ;
break ;
case 0x03 : /* XOR */
writepx [ i ] ^ = srcpx - > p8 [ i ] & mask32 . d ;
break ;
}
}
for ( int i = 0 ; i < 8 ; i + + ) {
da2 - > vram [ ( da2 - > vram_mask & destaddr ) | i ] = ( writepx [ i ] > > 24 ) & 0xff ;
da2 - > vram [ ( da2 - > vram_mask & ( destaddr + 8 ) ) | i ] = ( writepx [ i ] > > 16 ) & 0xff ;
}
}
void DA2_DrawColorWithBitmask ( uint32_t destaddr , uint8_t color , uint16_t mask , da2_t * da2 )
{
pixel32 srcpx ;
//fill data with input color
for ( int i = 0 ; i < 8 ; i + + )
srcpx . p8 [ i ] = ( color & ( 1 < < i ) ) ? 0xffffffff : 0 ; //read in word
DA2_WritePlaneDataWithBitmask ( destaddr , mask , & srcpx , da2 ) ;
}
/*
Param Desc
01 Color
03 Bit Shift
04 Select plane ?
05 Dir ( 10 or 11 ) + Command ? ( 40 or 48 )
08 Mask Left
09 Mask Right
0 A Plane Mask ?
0 B ROP ? ( 8 h or 200 h + 0 - 3 h )
0 D
20 Exec ( 1 )
21 ?
22 ?
23 Tile W
28 Tile H
29 Dest Addr
2 A Src Addr
2 B Tile Addr
33 Size W
35 Size H
*/
void DA2_CopyPlaneDataWithBitmask ( uint32_t srcaddr , uint32_t destaddr , uint16_t mask , da2_t * da2 )
{
pixel32 srcpx ;
srcaddr & = 0xfffffffe ;
srcaddr < < = 3 ;
for ( int i = 0 ; i < 8 ; i + + )
srcpx . p8 [ i ] = DA2_readvram_s ( ( srcaddr + 24 ) | i , da2 )
| ( DA2_readvram_s ( ( srcaddr + 16 ) | i , da2 ) < < 8 )
| ( DA2_readvram_s ( ( srcaddr + 8 ) | i , da2 ) < < 16 )
| ( DA2_readvram_s ( ( srcaddr + 0 ) | i , da2 ) < < 24 ) ; //read in word
DA2_WritePlaneDataWithBitmask ( destaddr , mask , & srcpx , da2 ) ;
}
void DA2_PutcharWithBitmask ( uint32_t srcaddr , uint32_t destaddr , uint16_t mask , da2_t * da2 )
{
pixel32 srcpx ;
if ( srcaddr > = DA2_FONTROM_SIZE ) {
da2_log ( " DA2 Putchar Addr Error %x \n " , srcaddr ) ;
return ;
}
for ( int i = 0 ; i < 8 ; i + + )
srcpx . p8 [ i ] = ( ( uint32_t ) da2 - > mmio . font [ srcaddr ] < < 24 )
| ( ( uint32_t ) da2 - > mmio . font [ srcaddr + 1 ] < < 16 )
| ( ( uint32_t ) da2 - > mmio . font [ srcaddr + 2 ] < < 8 )
| ( ( uint32_t ) da2 - > mmio . font [ srcaddr + 3 ] < < 0 ) ; //read in word
DA2_WritePlaneDataWithBitmask ( destaddr , mask , & srcpx , da2 ) ;
}
# ifdef ENABLE_DA2_DEBUGBLT
uint8_t pixel1tohex ( uint32_t addr , int index , da2_t * da2 ) {
uint8_t pixeldata = 0 ;
for ( int j = 0 ; j < 8 ; j + + ) {
if ( da2 - > vram [ ( da2 - > vram_mask & ( addr < < 3 ) ) | j ] & ( 1 < < ( 7 - index ) ) ) pixeldata + + ;
}
return pixeldata ;
}
void print_pixelbyte ( uint32_t addr , da2_t * da2 ) {
for ( int i = 0 ; i < 8 ; i + + )
{
pclog ( " %X " , pixel1tohex ( addr , i , da2 ) ) ;
}
}
void print_bytetobin ( uint8_t b ) {
for ( int i = 0 ; i < 8 ; i + + )
{
if ( b & 0x80 )
pclog ( " 1 " ) ;
else
pclog ( " 0 " ) ;
b < < = 1 ;
}
}
//Convert internal char code to Shift JIS code
inline int isKanji1 ( uint8_t chr ) { return ( chr > = 0x81 & & chr < = 0x9f ) | | ( chr > = 0xe0 & & chr < = 0xfc ) ; }
inline int isKanji2 ( uint8_t chr ) { return ( chr > = 0x40 & & chr < = 0x7e ) | | ( chr > = 0x80 & & chr < = 0xfc ) ; }
uint16_t IBMJtoSJIS ( uint16_t knj )
{
if ( knj < 0x100 ) return 0xffff ;
knj - = 0x100 ;
if ( knj < = 0x1f7d )
; /* do nothing */
else if ( knj > = 0xb700 & & knj < = 0xb75f ) {
knj - = 0x90ec ;
}
else if ( knj > = 0xb3f0 & & knj < = 0xb67f ) {
knj - = 0x906c ;
}
else if ( knj > = 0x8000 & & knj < = 0x8183 )
{
knj - = 0x5524 ;
}
else
return 0xffff ;
uint32_t knj1 = knj / 0xBC ;
uint32_t knj2 = knj - ( knj1 * 0xBC ) ;
knj1 + = 0x81 ;
if ( knj1 > 0x9F ) knj1 + = 0x40 ;
knj2 + = 0x40 ;
if ( knj2 > 0x7E ) knj2 + + ;
//if (!isKanji1(knj1)) return 0xffff;
//if (!isKanji2(knj2)) return 0xffff;
knj = knj1 < < 8 ;
knj | = knj2 ;
return knj ;
}
# endif
void da2_bitblt_load ( da2_t * da2 )
{
uint32_t value32 ;
uint64_t value64 ;
da2_log ( " BITBLT loading params \n " ) ;
//da2_log("BitBlt memory:\n");
//if (da2->bitblt.payload[0] != 0)
// for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++)
// {
// int i = j * 8;
// da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3],
// da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]);
// }
int i = 0 ;
while ( i < DA2_BLT_MEMSIZE )
{
if ( da2 - > bitblt . reg [ 0x20 ] & 0x1 )
break ;
switch ( da2 - > bitblt . payload [ i ] ) {
case 0x88 :
case 0x89 :
case 0x95 :
value32 = da2 - > bitblt . payload [ i + 3 ] ;
value32 < < = 8 ;
value32 | = da2 - > bitblt . payload [ i + 2 ] ;
da2_log ( " [%02x] %02x: %04x (%d) \n " , da2 - > bitblt . payload [ i ] , da2 - > bitblt . payload [ i + 1 ] , value32 , value32 ) ;
da2 - > bitblt . reg [ da2 - > bitblt . payload [ i + 1 ] ] = value32 ;
i + = 3 ;
break ;
case 0x91 :
value32 = da2 - > bitblt . payload [ i + 5 ] ;
value32 < < = 8 ;
value32 | = da2 - > bitblt . payload [ i + 4 ] ;
value32 < < = 8 ;
value32 | = da2 - > bitblt . payload [ i + 3 ] ;
value32 < < = 8 ;
value32 | = da2 - > bitblt . payload [ i + 2 ] ;
da2_log ( " [%02x] %02x: %08x (%d) \n " , da2 - > bitblt . payload [ i ] , da2 - > bitblt . payload [ i + 1 ] , value32 , value32 ) ;
da2 - > bitblt . reg [ da2 - > bitblt . payload [ i + 1 ] ] = value32 ;
i + = 5 ;
break ;
case 0x99 :
value64 = da2 - > bitblt . payload [ i + 7 ] ;
value64 < < = 8 ;
value64 = da2 - > bitblt . payload [ i + 6 ] ;
value64 < < = 8 ;
value64 = da2 - > bitblt . payload [ i + 5 ] ;
value64 < < = 8 ;
value64 | = da2 - > bitblt . payload [ i + 4 ] ;
value64 < < = 8 ;
value64 | = da2 - > bitblt . payload [ i + 3 ] ;
value64 < < = 8 ;
value64 | = da2 - > bitblt . payload [ i + 2 ] ;
da2 - > bitblt . reg [ da2 - > bitblt . payload [ i + 1 ] ] = value64 ;
da2_log ( " [%02x] %02x: %02x %02x %02x %02x %02x %02x \n " , da2 - > bitblt . payload [ i ] , da2 - > bitblt . payload [ i + 1 ] , da2 - > bitblt . payload [ i + 2 ] , da2 - > bitblt . payload [ i + 3 ] ,
da2 - > bitblt . payload [ i + 4 ] , da2 - > bitblt . payload [ i + 5 ] , da2 - > bitblt . payload [ i + 6 ] , da2 - > bitblt . payload [ i + 7 ] ) ;
i + = 7 ;
break ;
case 0x00 :
break ;
default :
da2_log ( " da2_ParseBLT: Unknown PreOP! \n " ) ;
break ;
}
i + + ;
}
da2 - > bitblt . exec = DA2_BLT_CIDLE ;
/* clear payload memory */
memset ( da2 - > bitblt . payload , 0x00 , DA2_BLT_MEMSIZE ) ;
da2 - > bitblt . payload_addr = 0 ;
/* [89] 20: 0001 (1) then execute payload */
if ( da2 - > bitblt . reg [ 0x20 ] & 0x1 )
{
# ifdef ENABLE_DA2_DEBUGBLT
for ( i = 0 ; i < DA2_DEBUG_BLTLOG_SIZE ; i + + ) {
//if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]);
}
for ( i = 0 ; i < DA2_DEBUG_BLTLOG_SIZE ; i + + ) {
da2 - > bitblt . debug_reg [ DA2_DEBUG_BLTLOG_SIZE * da2 - > bitblt . debug_reg_ip + i ] = da2 - > bitblt . reg [ i ] ;
}
da2 - > bitblt . debug_reg [ DA2_DEBUG_BLTLOG_SIZE * ( da2 - > bitblt . debug_reg_ip + 1 ) - 1 ] = 0 ;
da2 - > bitblt . debug_reg_ip + + ;
if ( da2 - > bitblt . debug_reg_ip > = DA2_DEBUG_BLTLOG_MAX ) da2 - > bitblt . debug_reg_ip = 0 ;
# endif
da2 - > bitblt . bitshift_destr = ( ( da2 - > bitblt . reg [ 0x3 ] > > 4 ) & 0x0f ) ; //set bit shift
da2 - > bitblt . raster_op = da2 - > bitblt . reg [ 0x0b ] & 0x03 ; //01 AND, 03 XOR
da2_log ( " bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x \n " , da2 - > bitblt . reg [ 0x5 ] , da2 - > bitblt . reg [ 0x0b ] , CS , cpu_state . pc ) ;
for ( int i = 0 ; i < = 0xb ; i + + )
da2_log ( " %02x " , da2 - > gdcreg [ i ] ) ;
da2_log ( " \n " ) ;
da2 - > bitblt . destaddr = da2 - > bitblt . reg [ 0x29 ] ;
da2 - > bitblt . size_x = da2 - > bitblt . reg [ 0x33 ] ;
da2 - > bitblt . size_y = da2 - > bitblt . reg [ 0x35 ] ;
da2 - > bitblt . destpitch = da2 - > bitblt . reg [ 0x21 ] ;
da2 - > bitblt . srcpitch = da2 - > bitblt . reg [ 0x22 ] ;
if ( da2 - > bitblt . reg [ 0x2F ] = = 0x90 ) //destaddr -= 2, length += 1;
{
da2 - > bitblt . destaddr - = 2 ;
da2 - > bitblt . size_x + = 1 ;
da2 - > bitblt . destpitch - = 2 ;
da2 - > bitblt . srcpitch - = 2 ;
}
da2 - > bitblt . fcolor = da2 - > bitblt . reg [ 0x0 ] ;
da2 - > bitblt . maskl = da2 - > bitblt . reg [ 0x8 ] ;
da2 - > bitblt . maskr = da2 - > bitblt . reg [ 0x9 ] ;
da2 - > bitblt . x = 0 ;
da2 - > bitblt . y = 0 ;
da2 - > bitblt . exec = DA2_BLT_CDONE ;
timer_set_delay_u64 ( & da2 - > bitblt . timer , da2 - > bitblt . timerspeed ) ;
if ( da2 - > bitblt . reg [ 0x2f ] < 0x80 ) //MS Paint 3.1 will cause hang up in 256 color mode
{
da2_log ( " bitblt not executed 2f:%x \n " , da2 - > bitblt . reg [ 0x2f ] ) ;
da2 - > bitblt . exec = DA2_BLT_CDONE ;
}
else if ( da2 - > bitblt . reg [ 0x10 ] = = 0xbc04 ) { /* Put char used by OS/2 (i'm not sure what the condition is) */
da2 - > bitblt . exec = DA2_BLT_CPUTCHAR ;
/* Todo: addressing */
//if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1;
//{
// da2->bitblt.destaddr += 2;
// da2->bitblt.size_x -= 1;
// da2->bitblt.destpitch += 2;
// da2->bitblt.srcpitch += 2;
//}
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x12 ] * 72 + 2 ;
da2 - > bitblt . destaddr + = 2 ;
da2 - > bitblt . srcpitch = 0 ;
da2 - > bitblt . raster_op = da2 - > bitblt . reg [ 0x05 ] & 0x03 ; /* XOR */
da2 - > bitblt . bitshift_destr + = 1 ;
2025-02-15 11:05:16 +09:00
# ifdef ENABLE_DA2_DEBUGBLT
uint32_t sjis_h = IBMJtoSJIS ( da2 - > bitblt . reg [ 0x12 ] ) > > 8 ;
uint32_t sjis_l = IBMJtoSJIS ( da2 - > bitblt . reg [ 0x12 ] ) & 0xff ;
2025-02-15 08:27:17 +09:00
da2_log ( " put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c \n " ,
da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y , sjis_h , sjis_l ) ;
2025-02-15 11:05:16 +09:00
# endif
2025-02-15 08:27:17 +09:00
}
else if ( da2 - > bitblt . reg [ 0x10 ] = = 0x0004 | | da2 - > bitblt . reg [ 0x10 ] = = 0x0E04 ) {
da2 - > bitblt . exec = DA2_BLT_CPUTCHAR ;
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x12 ] * 64 + 2 + DA2_FONTROM_BASESBCS ;
da2 - > bitblt . destaddr + = 2 ;
da2 - > bitblt . srcpitch = 0 ;
da2 - > bitblt . raster_op = da2 - > bitblt . reg [ 0x05 ] & 0x03 ; /* XOR */
da2 - > bitblt . bitshift_destr + = 1 ;
2025-02-15 11:05:16 +09:00
# ifdef ENABLE_DA2_DEBUGBLT
uint32_t sjis_h = IBMJtoSJIS ( da2 - > bitblt . reg [ 0x12 ] ) > > 8 ;
uint32_t sjis_l = IBMJtoSJIS ( da2 - > bitblt . reg [ 0x12 ] ) & 0xff ;
2025-02-15 08:27:17 +09:00
da2_log ( " put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c \n " ,
da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y , sjis_h , sjis_l ) ;
2025-02-15 11:05:16 +09:00
# endif
2025-02-15 08:27:17 +09:00
}
else if ( ( da2 - > bitblt . reg [ 0x5 ] & 0xfff0 ) = = 0x40 & & da2 - > bitblt . reg [ 0x3D ] = = 0 ) { /* Fill a rectangle(or draw a line) */
da2_log ( " fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x \n " ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y , da2 - > bitblt . reg [ 0x0 ] , da2 - > bitblt . reg [ 0x2F ] , da2 - > rowoffset * 2 ) ;
da2 - > bitblt . exec = DA2_BLT_CFILLRECT ;
da2 - > bitblt . destaddr + = 2 ;
}
else if ( ( da2 - > bitblt . reg [ 0x5 ] & 0xfff0 ) = = 0x0040 & & da2 - > bitblt . reg [ 0x3D ] = = 0x40 ) { /* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */
da2 - > bitblt . exec = DA2_BLT_CFILLTILE ;
da2 - > bitblt . destaddr + = 2 ;
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x2B ] ;
da2 - > bitblt . tile_w = da2 - > bitblt . reg [ 0x28 ] ;
da2_log ( " copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d \n " ,
da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr ,
da2 - > bitblt . reg [ 0x2B ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x2B ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y ) ;
}
else if ( ( da2 - > bitblt . reg [ 0x5 ] & 0xfff0 ) = = 0x1040 & & da2 - > bitblt . reg [ 0x3D ] = = 0x40 ) { /* Tiling a rectangle (transfer tile data multiple times) */
da2 - > bitblt . exec = DA2_BLT_CFILLTILE ;
da2 - > bitblt . destaddr + = 2 ;
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x2B ] ;
da2 - > bitblt . tile_w = da2 - > bitblt . reg [ 0x28 ] ;
da2_log ( " copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d \n " ,
da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr ,
da2 - > bitblt . reg [ 0x2B ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x2B ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y ) ;
}
else if ( ( da2 - > bitblt . reg [ 0x5 ] & 0xfff0 ) = = 0x1040 & & da2 - > bitblt . reg [ 0x3D ] = = 0x00 ) { /* Block transfer (range copy) */
da2 - > bitblt . exec = DA2_BLT_CCOPYF ;
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x2A ] ;
da2 - > bitblt . destaddr + = 2 ;
da2_log ( " copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d \n " ,
da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr ,
da2 - > bitblt . reg [ 0x2A ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x2A ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y ) ;
}
else if ( ( da2 - > bitblt . reg [ 0x5 ] & 0xfff0 ) = = 0x1140 & & da2 - > bitblt . reg [ 0x3D ] = = 0x00 ) { /* Block copy but reversed direction */
da2 - > bitblt . exec = DA2_BLT_CCOPYR ;
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x2A ] ;
da2 - > bitblt . destaddr - = 2 ;
da2 - > bitblt . srcaddr - = 2 ;
da2_log ( " copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d \n " ,
da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr ,
da2 - > bitblt . reg [ 0x2A ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x2A ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . reg [ 0x29 ] % ( da2 - > rowoffset * 2 ) , da2 - > bitblt . reg [ 0x29 ] / ( da2 - > rowoffset * 2 ) ,
da2 - > bitblt . size_x , da2 - > bitblt . size_y ) ;
//da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]);
}
}
}
void da2_bitblt_exec ( void * p )
{
da2_t * da2 = ( da2_t * ) p ;
timer_set_delay_u64 ( & da2 - > bitblt . timer , da2 - > bitblt . timerspeed ) ;
//da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y);
switch ( da2 - > bitblt . exec )
{
case DA2_BLT_CIDLE :
timer_disable ( & da2 - > bitblt . timer ) ;
break ;
case DA2_BLT_CLOAD :
da2 - > bitblt . indata = 0 ;
da2_bitblt_load ( da2 ) ;
break ;
case DA2_BLT_CFILLRECT :
//da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y);
if ( da2 - > bitblt . x > = da2 - > bitblt . size_x - 1 ) {
DA2_DrawColorWithBitmask ( da2 - > bitblt . destaddr , da2 - > bitblt . fcolor , da2 - > bitblt . maskr , da2 ) ;
if ( da2 - > bitblt . y > = da2 - > bitblt . size_y - 1 )
{
da2 - > bitblt . exec = DA2_BLT_CDONE ;
}
da2 - > bitblt . x = 0 ;
da2 - > bitblt . y + + ;
da2 - > bitblt . destaddr + = da2 - > bitblt . destpitch + 2 ;
}
else if ( da2 - > bitblt . x = = 0 ) {
DA2_DrawColorWithBitmask ( da2 - > bitblt . destaddr , da2 - > bitblt . fcolor , da2 - > bitblt . maskl , da2 ) ;
da2 - > bitblt . x + + ;
}
else {
DA2_DrawColorWithBitmask ( da2 - > bitblt . destaddr , da2 - > bitblt . fcolor , 0xffff , da2 ) ;
da2 - > bitblt . x + + ;
}
da2 - > bitblt . destaddr + = 2 ;
break ;
case DA2_BLT_CFILLTILE :
int32_t tileaddr = da2 - > bitblt . srcaddr + ( da2 - > bitblt . y % da2 - > bitblt . tile_w ) * 2 ;
if ( da2 - > bitblt . x > = da2 - > bitblt . size_x - 1 ) {
DA2_CopyPlaneDataWithBitmask ( tileaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskr , da2 ) ;
if ( da2 - > bitblt . y > = da2 - > bitblt . size_y - 1 )
{
da2 - > bitblt . exec = DA2_BLT_CDONE ;
}
da2 - > bitblt . x = 0 ;
da2 - > bitblt . y + + ;
da2 - > bitblt . destaddr + = da2 - > bitblt . destpitch + 2 ;
}
else if ( da2 - > bitblt . x = = 0 ) {
DA2_CopyPlaneDataWithBitmask ( tileaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskl , da2 ) ;
da2 - > bitblt . x + + ;
}
else {
DA2_CopyPlaneDataWithBitmask ( tileaddr , da2 - > bitblt . destaddr , 0xffff , da2 ) ;
da2 - > bitblt . x + + ;
}
da2 - > bitblt . destaddr + = 2 ;
break ;
case DA2_BLT_CCOPYF :
if ( da2 - > bitblt . x > = da2 - > bitblt . size_x - 1 ) {
DA2_CopyPlaneDataWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskr , da2 ) ;
if ( da2 - > bitblt . y > = da2 - > bitblt . size_y - 1 )
{
da2 - > bitblt . exec = DA2_BLT_CDONE ;
}
da2 - > bitblt . x = 0 ;
da2 - > bitblt . y + + ;
da2 - > bitblt . destaddr + = da2 - > bitblt . destpitch + 2 ;
da2 - > bitblt . srcaddr + = da2 - > bitblt . srcpitch + 2 ;
}
else if ( da2 - > bitblt . x = = 0 ) {
DA2_CopyPlaneDataWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskl , da2 ) ;
da2 - > bitblt . x + + ;
}
else {
DA2_CopyPlaneDataWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , 0xffff , da2 ) ;
da2 - > bitblt . x + + ;
}
da2 - > bitblt . destaddr + = 2 ;
da2 - > bitblt . srcaddr + = 2 ;
break ;
case DA2_BLT_CCOPYR :
if ( da2 - > bitblt . x > = da2 - > bitblt . size_x - 1 ) {
DA2_CopyPlaneDataWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskr , da2 ) ;
if ( da2 - > bitblt . y > = da2 - > bitblt . size_y - 1 )
{
da2 - > bitblt . exec = DA2_BLT_CDONE ;
}
da2 - > bitblt . x = 0 ;
da2 - > bitblt . y + + ;
da2 - > bitblt . destaddr - = da2 - > bitblt . destpitch ;
da2 - > bitblt . srcaddr - = da2 - > bitblt . srcpitch ;
da2 - > bitblt . destaddr - = 2 ;
da2 - > bitblt . srcaddr - = 2 ;
}
else if ( da2 - > bitblt . x = = 0 ) {
DA2_CopyPlaneDataWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskl , da2 ) ;
da2 - > bitblt . x + + ;
}
else {
DA2_CopyPlaneDataWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , 0xffff , da2 ) ;
da2 - > bitblt . x + + ;
}
da2 - > bitblt . destaddr - = 2 ;
da2 - > bitblt . srcaddr - = 2 ;
break ;
case DA2_BLT_CPUTCHAR :
//da2->bitblt.y += 2;
da2 - > bitblt . destaddr = da2 - > bitblt . reg [ 0x29 ] + da2 - > bitblt . x * 2 + da2 - > bitblt . y * 130 + 0 + 260 ;
2025-02-15 11:05:16 +09:00
//pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr);
2025-02-15 08:27:17 +09:00
//da2->bitblt.srcaddr += 2;
if ( da2 - > bitblt . reg [ 0x12 ] < 0x100 )
da2 - > bitblt . srcaddr = DA2_FONTROM_BASESBCS + da2 - > bitblt . reg [ 0x12 ] * 64 + ( da2 - > bitblt . x * 2 ) + ( da2 - > bitblt . y * 2 ) - 2 ;
else
da2 - > bitblt . srcaddr = da2 - > bitblt . reg [ 0x12 ] * 72 + ( da2 - > bitblt . x * 2 ) + ( da2 - > bitblt . y * 3 ) - 2 ;
2025-02-15 11:05:16 +09:00
//print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]);
//print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]);
//pclog("\n");
2025-02-15 08:27:17 +09:00
if ( da2 - > bitblt . x > = da2 - > bitblt . size_x - 1 ) {
//if (1) {
DA2_PutcharWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskr , da2 ) ;
if ( da2 - > bitblt . y > = da2 - > bitblt . size_y - 3 )
{
da2 - > bitblt . exec = DA2_BLT_CDONE ;
}
da2 - > bitblt . x = 0 ;
da2 - > bitblt . y + + ;
da2 - > bitblt . destaddr + = 130 ;
//da2->bitblt.destaddr += da2->bitblt.destpitch + 2;
//da2->bitblt.srcaddr += -1;
}
else if ( da2 - > bitblt . x = = 0 ) {
DA2_PutcharWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , da2 - > bitblt . maskl , da2 ) ;
da2 - > bitblt . x + + ;
//da2->bitblt.x++;
}
else {
DA2_PutcharWithBitmask ( da2 - > bitblt . srcaddr , da2 - > bitblt . destaddr , 0xffff , da2 ) ;
da2 - > bitblt . x + + ;
//da2->bitblt.x++;
}
//da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2;
////da2->bitblt.srcaddr += 2;
//da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2;
break ;
case DA2_BLT_CDONE :
/* initialize regs for debug dump */
for ( int i = 0 ; i < DA2_BLT_REGSIZE ; i + + ) {
if ( da2 - > bitblt . reg [ i ] ! = DA2_DEBUG_BLT_NEVERUSED ) da2 - > bitblt . reg [ i ] = DA2_DEBUG_BLT_USEDRESET ;
}
if ( da2 - > bitblt . indata ) da2 - > bitblt . exec = DA2_BLT_CLOAD ;
else da2 - > bitblt . exec = DA2_BLT_CIDLE ;
break ;
}
}
void da2_bitblt_dopayload ( da2_t * da2 ) {
if ( da2 - > bitblt . exec = = DA2_BLT_CIDLE )
{
da2 - > bitblt . exec = DA2_BLT_CLOAD ;
//timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed);
/* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */
da2_log ( " da2 Do bitblt \n " ) ;
while ( da2 - > bitblt . exec ! = DA2_BLT_CIDLE )
{
da2_bitblt_exec ( da2 ) ;
}
da2_log ( " da2 End bitblt %x \n " , da2 - > bitblt . exec ) ;
}
}
void da2_out ( uint16_t addr , uint16_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
int oldval ;
/*
3E0 3E1 Sequencer Registers ( undoc )
3E2 3E3 Font Registers ( undoc )
3E4 3E5 CRT Control Registers ( undoc )
3E8 3E9 Attribute Controller Registers ( undoc )
3 EA 3 EB 3 EC Graphics Contoller Registers
*/
switch ( addr )
{
case 0x3c6 : /* PEL Mask */
da2 - > dac_mask = val ;
break ;
case 0x3C7 : /* Read Address */
da2 - > dac_read = val ;
da2 - > dac_pos = 0 ;
break ;
case 0x3C8 : /* Write Address */
da2 - > dac_write = val ;
da2 - > dac_read = val - 1 ;
da2 - > dac_pos = 0 ;
break ;
case 0x3C9 : /* Data */
//da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI);
da2 - > dac_status = 0 ;
da2 - > fullchange = changeframecount ;
switch ( da2 - > dac_pos )
{
case 0 :
da2 - > dac_r = val ;
da2 - > dac_pos + + ;
break ;
case 1 :
da2 - > dac_g = val ;
da2 - > dac_pos + + ;
break ;
case 2 :
da2 - > vgapal [ da2 - > dac_write ] . r = da2 - > dac_r ;
da2 - > vgapal [ da2 - > dac_write ] . g = da2 - > dac_g ;
da2 - > vgapal [ da2 - > dac_write ] . b = val ;
//if (da2->ramdac_type == RAMDAC_8BIT)
// da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b);
//else
da2 - > pallook [ da2 - > dac_write ] = makecol32 ( ( da2 - > vgapal [ da2 - > dac_write ] . r & 0x3f ) * 4 , ( da2 - > vgapal [ da2 - > dac_write ] . g & 0x3f ) * 4 , ( da2 - > vgapal [ da2 - > dac_write ] . b & 0x3f ) * 4 ) ;
da2 - > dac_pos = 0 ;
da2 - > dac_write = ( da2 - > dac_write + 1 ) & 255 ;
break ;
}
break ;
case LS_INDEX :
da2 - > ioctladdr = val ;
break ;
case LS_DATA :
//da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc);
if ( da2 - > ioctladdr > 0xf ) return ;
if ( da2 - > ioctl [ da2 - > ioctladdr & 15 ] ! = val )
da2_log ( " ioctl changed %x: %x -> %x %04X:%04X \n " , da2 - > ioctladdr & 15 , da2 - > ioctl [ da2 - > ioctladdr & 15 ] , val , cs > > 4 , cpu_state . pc ) ;
oldval = da2 - > ioctl [ da2 - > ioctladdr ] ;
da2 - > ioctl [ da2 - > ioctladdr ] = val ;
if ( oldval ! = val ) {
if ( da2 - > ioctladdr = = LS_RESET & & val & 0x01 ) /* Reset register */
da2_reset_ioctl ( da2 ) ;
else if ( da2 - > ioctladdr = = LS_MODE & & ( ( oldval ^ val ) & 0x03 ) ) /* Mode register */
{
da2 - > fullchange = changeframecount ;
da2_recalctimings ( da2 ) ;
da2_updatevidselector ( da2 ) ;
}
else if ( da2 - > ioctladdr = = LS_MMIO & & ( ! ( val & 0x01 ) ) ) /* MMIO register */
{
//da2->bitblt.indata = 1;
}
}
break ;
case LF_INDEX :
da2 - > fctladdr = val ;
break ;
case LF_DATA :
//da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc);
if ( da2 - > fctladdr > 0x1f ) return ;
if ( da2 - > fctl [ da2 - > fctladdr & 0x1f ] ! = val )
da2_log ( " fctl changed %x: %x -> %x %04X:%04X \n " , da2 - > fctladdr & 0x1f , da2 - > fctl [ da2 - > fctladdr & 0x1f ] , val , cs > > 4 , cpu_state . pc ) ;
oldval = da2 - > fctl [ da2 - > fctladdr ] ;
da2 - > fctl [ da2 - > fctladdr ] = val ;
if ( da2 - > fctladdr = = 0 & & oldval ! = val )
{
da2 - > fullchange = changeframecount ;
da2_recalctimings ( da2 ) ;
}
break ;
case LC_INDEX :
da2 - > crtcaddr = val ;
break ;
case LC_DATA :
if ( da2 - > crtcaddr > 0x1f ) return ;
//if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ))
// da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc);
if ( ! ( da2 - > crtc [ da2 - > crtcaddr ] ^ val ) ) return ;
switch ( da2 - > crtcaddr ) {
case LC_CRTC_OVERFLOW :
//return;
break ;
case LC_MAXIMUM_SCAN_LINE :
if ( ! ( da2 - > ioctl [ LS_MODE ] & 0x01 ) ) val = 0 ;
break ;
case LC_START_ADDRESS_HIGH :
//if (da2->crtc[0x1c] & 0x40) return;
break ;
case LC_VERTICAL_TOTALJ : /* Vertical Total */
case LC_VERTICAL_SYNC_START : /* Vertical Retrace Start Register */
case LC_V_DISPLAY_ENABLE_END : /* Vertical Display End Register */
case LC_START_VERTICAL_BLANK : /* Start Vertical Blank Register */
//val = 0x400; //for debugging bitblt
break ;
case LC_VIEWPORT_SELECT : /* ViewPort Select? */
//return;
break ;
case LC_VIEWPORT_NUMBER : /* Compatibility? */
break ;
}
da2 - > crtc [ da2 - > crtcaddr ] = val ;
switch ( da2 - > crtcaddr ) {
case LC_H_DISPLAY_ENABLE_END :
case LC_VERTICAL_TOTALJ :
case LC_MAXIMUM_SCAN_LINE :
case LC_START_ADDRESS_HIGH :
case LC_START_ADDRESS_LOW :
case LC_VERTICAL_SYNC_START :
case LC_V_DISPLAY_ENABLE_END :
case LC_START_VERTICAL_BLANK :
case LC_END_VERTICAL_BLANK :
case LC_VIEWPORT_PRIORITY :
da2 - > fullchange = changeframecount ;
da2_recalctimings ( da2 ) ;
break ;
default :
break ;
}
break ;
case LV_PORT :
//da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc);
if ( ! da2 - > attrff )
{
// da2->attraddr = val & 31;
da2 - > attraddr = val & 0x3f ;
if ( ( val & 0x20 ) ! = ( da2 - > attr_palette_enable & 0x20 ) )
{
da2 - > fullchange = 3 ;
da2 - > attr_palette_enable = val & 0x20 ;
da2_recalctimings ( da2 ) ;
}
//da2_log("set attraddr: %X\n", da2->attraddr);
}
else
{
if ( ( da2 - > attraddr = = LV_PANNING ) & & ( da2 - > attrc [ LV_PANNING ] ! = val ) )
da2 - > fullchange = changeframecount ;
if ( da2 - > attrc [ da2 - > attraddr & 0x3f ] ! = val )
da2_log ( " attr changed %x: %x -> %x \n " , da2 - > attraddr & 0x3f , da2 - > attrc [ da2 - > attraddr & 0x3f ] , val ) ;
da2 - > attrc [ da2 - > attraddr & 0x3f ] = val ;
//da2_log("set attrc %x: %x\n", da2->attraddr & 31, val);
if ( da2 - > attraddr < 16 )
da2 - > fullchange = changeframecount ;
if ( da2 - > attraddr = = LV_MODE_CONTROL | | da2 - > attraddr < 0x10 )
{
for ( int c = 0 ; c < 16 ; c + + )
{
//if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4);
//else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4);
if ( da2 - > attrc [ LV_MODE_CONTROL ] & 0x80 ) da2 - > egapal [ c ] = da2 - > attrc [ c ] & 0xf ;
else da2 - > egapal [ c ] = da2 - > attrc [ c ] & 0x3f ;
}
}
switch ( da2 - > attraddr )
{
case LV_COLOR_PLANE_ENAB :
if ( ( val & 0xff ) ! = da2 - > plane_mask )
da2 - > fullchange = changeframecount ;
da2 - > plane_mask = val & 0xff ;
break ;
case LV_CURSOR_CONTROL :
switch ( val & 0x18 ) {
case 0x08 : //fast blink
da2 - > blinkconf = 0x10 ;
break ;
case 0x18 : //slow blink
da2 - > blinkconf = 0x20 ;
break ;
default : //no blink
da2 - > blinkconf = 0xff ;
break ;
}
break ;
case LV_MODE_CONTROL :
case LV_ATTRIBUTE_CNTL :
case LV_COMPATIBILITY :
da2_recalctimings ( da2 ) ;
break ;
default :
break ;
}
}
da2 - > attrff ^ = 1 ;
break ;
case 0x3E9 :
/* VZ Editor's CURSOR.COM writes data via this port */
da2 - > attrc [ da2 - > attraddr & 0x3f ] = val ;
break ;
case LG_INDEX :
da2 - > gdcaddr = val ;
break ;
case LG_DATA :
//if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val);
//if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI);
switch ( da2 - > gdcaddr & 0x1f )
{
case LG_READ_MAP_SELECT :
da2 - > readplane = val & 0x7 ;
break ;
case LG_MODE :
da2 - > writemode = val & 3 ;
break ;
case LG_MAP_MASKJ :
da2 - > writemask = val & 0xff ;
break ;
case LG_COMMAND :
break ;
case LG_SET_RESET_2 :
da2_log ( " !!!DA2 GC Out addr %03X idx 10 val %02X \n " , addr , val ) ;
return ;
}
da2 - > gdcreg [ da2 - > gdcaddr & 15 ] = val & 0xff ;
break ;
//case 0x3ed: /* used by Windows 3.1 display driver */
// da2->gdcreg[5] = val & 0xff;
// break;
default :
da2_log ( " DA2? Out addr %03X val %02X \n " , addr , val ) ;
break ;
}
}
uint16_t da2_in ( uint16_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
uint16_t temp ;
switch ( addr )
{
case 0x3c3 :
temp = 0 ;
break ;
case 0x3c6 : temp = da2 - > dac_mask ;
break ;
case 0x3c7 : temp = da2 - > dac_status ;
break ;
case 0x3c8 : temp = da2 - > dac_write ;
break ;
case 0x3c9 :
da2 - > dac_status = 3 ;
switch ( da2 - > dac_pos )
{
case 0 :
da2 - > dac_pos + + ;
temp = da2 - > vgapal [ da2 - > dac_read ] . r & 0x3f ;
break ;
case 1 :
da2 - > dac_pos + + ;
temp = da2 - > vgapal [ da2 - > dac_read ] . g & 0x3f ;
break ;
case 2 :
da2 - > dac_pos = 0 ;
da2 - > dac_read = ( da2 - > dac_read + 1 ) & 255 ;
temp = da2 - > vgapal [ ( da2 - > dac_read - 1 ) & 255 ] . b & 0x3f ;
break ;
}
break ;
case LS_INDEX :
temp = da2 - > ioctladdr ;
break ;
case LS_DATA :
//da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?)
if ( da2 - > ioctladdr > 0xf ) return DA2_INVALIDACCESS8 ;
temp = da2 - > ioctl [ da2 - > ioctladdr ] ;
if ( da2 - > ioctladdr = = LS_STATUS ) { /* Status register */
if ( da2 - > attrc [ LV_COMPATIBILITY ] & 0x08 ) { /* for detecting monitor type and cable wiring */
if ( da2 - > monitorid = = DA2_DCONFIG_MONTYPE_MONO ) {
/* grayscale monitor */
if ( ( da2 - > vgapal [ 0 ] . r > = 10 ) | | ( da2 - > vgapal [ 0 ] . g > = 40 ) | | ( da2 - > vgapal [ 0 ] . b > = 10 ) )
temp & = 0x7F ; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */
else
temp | = 0x80 ; /* Active when the RGB output voltage is low and the cable is connected to a color monitor.
If the cable or the monitor is wrong , it becomes inactive . */
} else {
/* color monitor */
if ( ( da2 - > vgapal [ 0 ] . r + da2 - > vgapal [ 0 ] . g + da2 - > vgapal [ 0 ] . b ) > = 80 )
temp & = 0x7F ;
else
temp | = 0x80 ;
}
} else {
temp | = 0x80 ;
}
temp & = 0xf6 ; //clear busy bits
if ( da2 - > bitblt . indata ) /* for OS/2 J1.3 */
da2_bitblt_dopayload ( da2 ) ;
if ( da2 - > bitblt . exec ! = DA2_BLT_CIDLE )
{
//da2_log("exec:%x\n", da2->bitblt.exec);
temp | = 0x08 ; //wait(bit 3 + bit 0)
//if (!da2->bitblt.timer.enabled)
//{
// da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc);
// timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed);
//}
}
if ( da2 - > bitblt . indata )
temp | = 0x01 ;
//da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc);
}
//da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc);
break ;
case LF_INDEX :
temp = da2 - > fctladdr ;
break ;
case LF_DATA :
if ( da2 - > fctladdr > 0x1f ) return DA2_INVALIDACCESS8 ;
temp = da2 - > fctl [ da2 - > fctladdr ] ;
break ;
case LC_INDEX :
temp = da2 - > crtcaddr ;
break ;
case LC_DATA :
if ( da2 - > crtcaddr > 0x1f ) return DA2_INVALIDACCESS8 ;
temp = da2 - > crtc [ da2 - > crtcaddr ] ;
break ;
case LV_PORT :
temp = da2 - > attraddr | da2 - > attr_palette_enable ;
break ;
case 0x3E9 :
if ( da2 - > attraddr = = LV_RAS_STATUS_VIDEO ) /* this may equiv to 3ba / 3da Input Status Register 1 */
{
if ( da2 - > cgastat & 0x01 )
da2 - > cgastat & = ~ 0x30 ;
else
da2 - > cgastat ^ = 0x30 ;
temp = da2 - > cgastat ;
}
else
temp = da2 - > attrc [ da2 - > attraddr ] ;
//da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc);
da2 - > attrff = 0 ; /* reset flipflop (VGA does not reset flipflop) */
break ;
case LG_INDEX :
temp = da2 - > gdcaddr ;
break ;
case LG_DATA :
temp = da2 - > gdcreg [ da2 - > gdcaddr & 0x1f ] ;
//da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc);
break ;
}
//da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
return temp ;
}
/*
* Write I / O
* out b ( idx ) , out b ( data ) , out b ( data )
* out b ( idx ) , out w ( data )
* out b ( idx ) , out w ( data ) , out b ( data )
* out w ( idx )
* Read I / O
* out b ( idx ) , in b ( data )
* out b ( idx ) , in b , in b ( data )
* out b ( idx ) , in w ( data )
*/
void da2_outb ( uint16_t addr , uint8_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
//da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
da2 - > inflipflop = 0 ;
switch ( addr )
{
case LS_DATA :
case LF_DATA :
case LC_DATA :
case LG_DATA :
if ( da2 - > outflipflop )
{
/* out b(idx), out b(data), out b(data) */
da2 - > iolatch | = ( uint16_t ) val < < 8 ;
da2 - > outflipflop = 0 ;
}
else
{ //
da2 - > iolatch = val ;
da2 - > outflipflop = 1 ;
}
break ;
case LS_INDEX :
case LF_INDEX :
case LC_INDEX :
case LG_INDEX :
default :
da2 - > iolatch = val ;
da2 - > outflipflop = 0 ;
break ;
}
da2_out ( addr , da2 - > iolatch , da2 ) ;
}
void da2_outw ( uint16_t addr , uint16_t val , void * p )
{
//da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
da2_t * da2 = ( da2_t * ) p ;
da2 - > inflipflop = 0 ;
switch ( addr )
{
case LS_INDEX :
case LF_INDEX :
case LC_INDEX :
case LG_INDEX :
da2_out ( addr , val & 0xff , da2 ) ;
da2 - > iolatch = val > > 8 ;
da2_out ( addr + 1 , da2 - > iolatch , da2 ) ;
da2 - > outflipflop = 1 ;
break ;
case LV_PORT :
da2 - > attrff = 0 ;
da2_out ( addr , val & 0xff , da2 ) ;
da2_out ( addr , val > > 8 , da2 ) ;
da2 - > outflipflop = 0 ;
break ;
case 0x3EC :
//da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc);
da2_out ( LG_DATA , val > > 8 , da2 ) ;
break ;
case 0x3ED :
da2 - > gdcaddr = LG_MODE ;
da2_out ( LG_DATA , val , da2 ) ;
break ;
case LS_DATA :
case LF_DATA :
case LC_DATA :
case LG_DATA :
default :
da2_out ( addr , val , da2 ) ;
da2 - > outflipflop = 0 ;
break ;
case 0x3EE :
da2_log ( " DA2 Outw addr %03X val %04X %04X:%04X \n " , addr , val , cs > > 4 , cpu_state . pc ) ;
da2 - > reg3ee [ val & 0xff ] = val > > 8 ;
break ;
}
}
uint8_t da2_inb ( uint16_t addr , void * p )
{
uint8_t temp ;
da2_t * da2 = ( da2_t * ) p ;
da2 - > outflipflop = 0 ;
switch ( addr )
{
case LC_DATA :
if ( da2 - > inflipflop )
{
/* out b(idx), in b(low data), in b(high data) */
temp = da2 - > iolatch > > 8 ;
da2 - > inflipflop = 0 ;
}
else
{ //
da2 - > iolatch = da2_in ( addr , da2 ) ;
temp = da2 - > iolatch & 0xff ;
da2 - > inflipflop = 1 ;
}
break ;
case LS_INDEX :
case LF_INDEX :
case LC_INDEX :
case LG_INDEX :
case LS_DATA :
case LF_DATA :
case LG_DATA :
default :
temp = da2_in ( addr , da2 ) & 0xff ;
da2 - > inflipflop = 0 ;
break ;
}
//da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
return temp ;
}
uint16_t da2_inw ( uint16_t addr , void * p )
{
//uint16_t temp;
da2_t * da2 = ( da2_t * ) p ;
da2 - > inflipflop = 0 ;
da2 - > outflipflop = 0 ;
return da2_in ( addr , da2 ) ;
}
/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */
uint8_t da2_in_ISR ( uint16_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
uint8_t temp = 0 ;
if ( addr = = 0x3da ) {
if ( da2 - > cgastat & 0x01 )
da2 - > cgastat & = ~ 0x30 ;
else
da2 - > cgastat ^ = 0x30 ;
temp = da2 - > cgastat ;
}
//da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc);
return temp ;
}
void da2_out_ISR ( uint16_t addr , uint8_t val , void * p )
{
//da2_t* da2 = (da2_t*)p;
da2_log ( " DA2D Out %04X %04X %04X:%04X \n " , addr , val , cs > > 4 , cpu_state . pc ) ;
}
/*
The IBM 5550 character mode addresses video memory between E0000h and E0FFFh .
[ Character drawing ]
SBCS :
1 2 . . . 13
1 | H . Grid
| - - - - - - - - - - - - - - - -
2 | Space
3 V |
. |
G | Font Pattern
r | ( 12 x24 pixels )
i |
d |
26 | ________________
27 Space
- - - - - - - - - - - - - - - -
28 Underscore ]
- - - - - - - - - - - - - - - - > Cursor Position
29 ]
DBCS :
1 2 . . . 13 1 2 . . . 12 13
1 | H . Grid | H . Grid |
- | - - - - - - - - - - - - - - - - - - - - - - - - - - | -
2 | Space | Space |
- | - - - - - - - - - - - - - - - - - - - - - - - - - - | -
3 V | | | S
. | | | p
G | Font Pattern | a
r | ( 24 x24 pixels ) | c
i | | | e
d | | |
26 | _____________ | ____________ |
27 | Space | Space
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28 | Underscore | Underscore ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > Cursor Position
29 | | ]
[ Attributes ]
Video mode 08 h :
7 6 5 4 3 2 1 0
Blink | Under | HGrid | VGrid | Bright | Revers | FntSet | DBCS / SBCS |
Video mode 0 Eh :
- Blue | - Green | HGrid | VGrid | - Red | Revers | FntSet | DBCS / SBCS |
Bit 1 switches the font bank to the Extended SBCS . DOS K3 . x loads APL characters from $ SYSEX24 . FNT into it .
DOS Bunsho Program transfers 1 / 2 and 1 / 4 fonts fron the font ROM to the Extended SBCS .
This bit is not used for DBCS , but some apps set it as that column is right half of DBCS .
[ Font ROM Map ( DA2 , Japanese ) ]
The Font ROM can be accessed via 128 KB memory window located at A0000 - BFFFFh .
Bank 0
4800 - *
Bank 1 , 2 , 3
* - *
Bank 4
* - 0 DB6Fh ( 4800 - 8 DB6Fh ) : JIS X 020 8 DBCS ( 24 x 24 ) ( IBMJ code : 100 - 1F 7 Dh )
10000 - 16 D1Fh ( 90000 - 96 D1Fh ) : IBM Extended Characters ( IBMJ code : 2 ADC - 2 C5Fh )
18000 - 1 BFCFh ( 98000 - 9 BFCFh ) : JIS X 0201 SBCS ( 13 x 30 )
1 C000 - 1FF FFh ( 9 C000 - 9FF FFh ) : Codepage 437 characters ( 13 x 30 )
Bank 5
00000 - 0 C68Fh ( A0000 - AC68Fh ) : Gaiji used by DOS Bunsho
10000 - 13FF Fh ( B0000 - B3FFFh ) : Extended SBCS ( 13 x 30 )
14000 - 1477F h ( B4000 - B477Fh ) : Half - width box drawing characters used by DOS Bunsho
16000 - 17FF Fh ( B6000 - B7FFFh ) : Codepage 850 characters ( 13 x 30 )
18000 - 1 A3FFh ( B8000 - BA3FFh ) : CAD control icons and box drawing characters ( 32 x 32 )
Some models have the signature 80 h , 01 h placed at Bank 0 : 1 AFFEh . ( it disables hardware text drawing in OS / 2 J1 .3 )
[ Font ROM Map ( DA3 , Traditional Chinese ) ]
Bank 0 - 11 : Valid Font ROM data
Bank 12 : Alias of bank 11 ( At least , DOS T5 .0 uses this on purpose . )
Bank 13 : All addresses return 0xFF
[ Gaiji RAM Map ( DA2 ) ]
Bank 0 00000 - 1FF FFh placed between A0000h - BFFFFh
00000 - 1F 7FF h ( A0000 - BF7FFh ) : Gaiji Non - resident ( Kuten 103 - 114 ku , IBM : 2674 - 2 ADBh ) 1008 chs 128 bytes
1F 800 - 1FF FFh ( BF800 - BFFFFh ) : Gaiji Resident ( SJIS : F040 - F04Fh , IBM : 2384 - 2393 h ) 16 chs
Bank 1 20000 - 3FF FFh placed between A0000h - BFFFFh
20000 - 33FF Fh ( A0000 - B3FFFh ) : Gaiji Resident ( SJIS : F050 - F39Ch , IBM : 2394 - 2613 h ) 640 chs
34000 - 37FF Fh ( B4000 - B7FFFh ) : Basic SBCS ( 00 - FFh , ATTR bit 1 = off )
38000 - 3 AFFFh ( B8000 - BAFFFh ) : Gaiji Resident ( SJIS : F39D - F3FCh , IBM : 2614 - 2673 h ) 96 chs
3 C000 - 3FF FFh ( BC000 - BFFFFh ) : Extended SBCS ( 00 - FFh , ATTR bit 1 = on )
[ IBMJ code to Gaiji address conv tbl from DOS K3 .3 ]
A B C
2 ADC , 2 C5F , + 5524 - - > 8000
2614 , 2673 , + 90 EC - - > B700
2384 , 2613 , + 906 C - - > B3F0
06 82 , 1F 7 D , + 0000
8000 - 8183 h 184 h ( 388 characters ) IBM Extended Characters
B3F0 - B75Fh 370 h ( 880 characters ) User - defined Characters
*/
/* Get character line pattern from jfont rom or gaiji volatile memory */
uint32_t getfont_ps55dbcs ( int32_t code , int32_t line , void * p ) {
da2_t * da2 = ( da2_t * ) p ;
uint32_t font = 0 ;
int32_t fline = line - 2 ; //Start line of drawing character (line >= 1 AND line < 24 + 1 )
if ( code > = 0x8000 & & code < = 0x8183 ) code - = 0x6000 ; //shift for IBM extended characters (I don't know how the real card works.)
if ( code < DA2_FONTROM_SIZE / 72 & & fline > = 0 & & fline < 24 ) {
font = da2 - > mmio . font [ code * 72 + fline * 3 ] ; //1111 1111
font < < = 8 ; //1111 1111 0000 0000
font | = da2 - > mmio . font [ code * 72 + fline * 3 + 1 ] & 0xf0 ; //1111 1111 2222 0000
font > > = 1 ; //0111 1111 1222 2000
font < < = 4 ; //0111 1111 1222 2000 0000
font | = da2 - > mmio . font [ code * 72 + fline * 3 + 1 ] & 0x0f ; //0111 1111 1222 2000 2222
font < < = 8 ; //0111 1111 1222 2000 2222 0000 0000
font | = da2 - > mmio . font [ code * 72 + fline * 3 + 2 ] ; //0111 1111 1222 2000 2222 3333 3333
font < < = 4 ; //0111 1111 1222 2000 2222 3333 3333 0000
//font >>= 1;//put blank at column 1 (and 26)
}
else if ( code > = 0xb000 & & code < = 0xb75f )
{
//convert code->address in gaiji memory
code - = 0xb000 ;
code * = 0x80 ;
//code += 0xf800;
font = da2 - > mmio . ram [ code + line * 4 ] ;
font < < = 8 ;
font | = da2 - > mmio . ram [ code + line * 4 + 1 ] ;
font < < = 8 ;
font | = da2 - > mmio . ram [ code + line * 4 + 2 ] ;
font < < = 8 ;
font | = da2 - > mmio . ram [ code + line * 4 + 3 ] ;
}
else if ( code > DA2_FONTROM_SIZE )
font = 0xffffffff ;
else
font = 0 ;
return font ;
}
/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */
uint8_t IRGBtoBGRI ( uint8_t attr )
{
attr = ( ( attr & 0x01 ) < < 7 ) | ( ( attr & 0x02 ) < < 5 ) | ( ( attr & 0x04 ) < < 3 ) | ( ( attr & 0x08 ) < < 1 ) ;
return attr > > = 4 ;
}
/* Get the foreground color from the attribute byte */
uint8_t getPS55ForeColor ( uint8_t attr , da2_t * da2 )
{
uint8_t foreground = ~ attr & 0x08 ; // 0000 1000
foreground < < = 2 ; //0010 0000
foreground | = ~ attr & 0xc0 ; // 1110 0000
foreground > > = 4 ; //0000 1110
if ( da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x40 ) foreground | = 0x01 ; //bright color palette
return foreground ;
}
void da2_render_blank ( da2_t * da2 )
{
int x , xx ;
if ( da2 - > firstline_draw = = 2000 )
da2 - > firstline_draw = da2 - > displine ;
da2 - > lastline_draw = da2 - > displine ;
for ( x = 0 ; x < da2 - > hdisp ; x + + )
{
for ( xx = 0 ; xx < 13 ; xx + + ) ( ( uint32_t * ) buffer32 - > line [ da2 - > displine ] ) [ ( x * 13 ) + xx + 32 ] = 0 ;
}
}
/* Display Adapter Mode 8, E Drawing */
static void da2_render_text ( da2_t * da2 )
{
if ( da2 - > firstline_draw = = 2000 )
da2 - > firstline_draw = da2 - > displine ;
da2 - > lastline_draw = da2 - > displine ;
if ( da2 - > fullchange )
{
int offset = ( 8 - da2 - > scrollcache ) + 24 ;
uint32_t * p = & ( ( uint32_t * ) buffer32 - > line [ da2 - > displine ] ) [ offset ] ;
int x ;
int drawcursor ;
uint8_t chr , attr ;
int fg , bg ;
uint32_t chr_dbcs ;
int chr_wide = 0 ;
//da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc);
for ( x = 0 ; x < da2 - > hdisp ; x + = 13 )
{
chr = da2 - > cram [ ( da2 - > ma ) & da2 - > vram_display_mask ] ;
attr = da2 - > cram [ ( ( da2 - > ma ) + 1 ) & da2 - > vram_display_mask ] ;
//if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr);
if ( da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x80 ) //IO 3E8h, Index 1Dh
{ //--Parse attribute byte in color mode--
bg = 0 ; //bg color is always black (the only way to change background color is programming PAL)
fg = getPS55ForeColor ( attr , da2 ) ;
if ( attr & 0x04 ) { //reverse 0000 0100
bg = fg ;
fg = 0 ;
}
}
else
{ //--Parse attribute byte in monochrome mode--
if ( attr & 0x08 ) fg = 3 ; //Highlight 0000 1000
else fg = 2 ;
bg = 0 ; //Background is always color #0 (default is black)
if ( ! ( ~ attr & 0xCC ) ) //Invisible 11xx 11xx -> 00xx 00xx
{
fg = bg ;
attr & = 0x33 ; //disable blinkking, underscore, highlight and reverse
}
if ( attr & 0x04 ) { //reverse 0000 0100
bg = fg ;
fg = 0 ;
}
// Blinking 1000 0000
fg = ( ( da2 - > blink & 0x20 ) | | ( ! ( attr & 0x80 ) ) ) ? fg : bg ;
//if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]);
}
//Draw character
for ( uint32_t n = 0 ; n < 13 ; n + + ) p [ n ] = da2 - > pallook [ da2 - > egapal [ bg ] ] ; //draw blank
// SBCS or DBCS left half
if ( chr_wide = = 0 ) {
if ( attr & 0x01 ) chr_wide = 1 ;
//chr_wide = 0;
// Stay drawing If the char code is DBCS and not at last column.
if ( chr_wide ) {
//Get high DBCS code from the next video address
chr_dbcs = da2 - > cram [ ( ( da2 - > ma ) + 2 ) & da2 - > vram_display_mask ] ;
chr_dbcs < < = 8 ;
chr_dbcs | = chr ;
// Get the font pattern
uint32_t font = getfont_ps55dbcs ( chr_dbcs , da2 - > sc , da2 ) ;
// Draw 13 dots
for ( uint32_t n = 0 ; n < 13 ; n + + ) {
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( font & 0x80000000 ) ? fg : bg ] ] ;
font < < = 1 ;
}
}
else {
// the char code is SBCS (ANK)
uint32_t fontbase ;
if ( attr & 0x02 ) //second map of SBCS font
fontbase = DA2_GAIJIRAM_SBEX ;
else
fontbase = DA2_GAIJIRAM_SBCS ;
uint16_t font = da2 - > mmio . ram [ fontbase + chr * 0x40 + da2 - > sc * 2 ] ; // w13xh29 font
font < < = 8 ;
font | = da2 - > mmio . ram [ fontbase + chr * 0x40 + da2 - > sc * 2 + 1 ] ; // w13xh29 font
//if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font);
// Draw 13 dots
for ( uint32_t n = 0 ; n < 13 ; n + + ) {
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( font & 0x8000 ) ? fg : bg ] ] ;
font < < = 1 ;
}
}
}
// right half of DBCS
else
{
uint32_t font = getfont_ps55dbcs ( chr_dbcs , da2 - > sc , da2 ) ;
// Draw 13 dots
for ( uint32_t n = 0 ; n < 13 ; n + + ) {
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( font & 0x8000 ) ? fg : bg ] ] ;
font < < = 1 ;
}
chr_wide = 0 ;
}
//Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly.
if ( da2 - > sc = = 27 & & attr & 0x40 & & ~ da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x80 ) { //Underscore only in monochrome mode
for ( uint32_t n = 0 ; n < 13 ; n + + )
p [ n ] = da2 - > pallook [ da2 - > egapal [ fg ] ] ; //under line (white)
}
//Column 1 (Vertical Line)
if ( attr & 0x10 ) {
p [ 0 ] = da2 - > pallook [ da2 - > egapal [ ( da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x80 ) ? IRGBtoBGRI ( da2 - > attrc [ LV_GRID_COLOR_0 ] ) : 2 ] ] ; //vertical line (white)
}
if ( da2 - > sc = = 0 & & attr & 0x20 & & ~ da2 - > attrc [ LV_PAS_STATUS_CNTRL ] ) { //HGrid
for ( uint32_t n = 0 ; n < 13 ; n + + )
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x80 ) ? IRGBtoBGRI ( da2 - > attrc [ LV_GRID_COLOR_0 ] ) : 2 ] ] ; //horizontal line (white)
}
//Drawing text cursor
drawcursor = ( ( da2 - > ma = = da2 - > ca ) & & da2 - > con & & da2 - > cursoron ) ;
if ( drawcursor & & da2 - > sc > = da2 - > crtc [ LC_CURSOR_ROW_START ] & & da2 - > sc < = da2 - > crtc [ LC_CURSOR_ROW_END ] )
{
int cursorwidth = ( da2 - > crtc [ LC_COMPATIBILITY ] & 0x20 ? 26 : 13 ) ;
int cursorcolor = ( da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x80 ) ? IRGBtoBGRI ( da2 - > attrc [ LV_CURSOR_COLOR ] ) : 2 ; //Choose color 2 if mode 8
fg = ( da2 - > attrc [ LV_PAS_STATUS_CNTRL ] & 0x80 ) ? getPS55ForeColor ( attr , da2 ) : ( ( attr & 0x08 ) ? 3 : 2 ) ;
bg = 0 ;
if ( attr & 0x04 ) { //Color 0 if reverse
bg = fg ;
fg = 0 ;
}
for ( uint32_t n = 0 ; n < cursorwidth ; n + + )
if ( p [ n ] = = da2 - > pallook [ da2 - > egapal [ cursorcolor ] ] | | da2 - > egapal [ bg ] = = da2 - > egapal [ cursorcolor ] )
p [ n ] = ( p [ n ] = = da2 - > pallook [ da2 - > egapal [ bg ] ] ) ? da2 - > pallook [ da2 - > egapal [ fg ] ] : da2 - > pallook [ da2 - > egapal [ bg ] ] ;
else
p [ n ] = ( p [ n ] = = da2 - > pallook [ da2 - > egapal [ bg ] ] ) ? da2 - > pallook [ da2 - > egapal [ cursorcolor ] ] : p [ n ] ;
}
da2 - > ma + = 2 ;
p + = 13 ;
}
da2 - > ma & = da2 - > vram_display_mask ;
//da2->writelines++;
}
}
/* Display Adapter Mode 3 Drawing */
static void da2_render_textm3 ( da2_t * da2 )
{
if ( da2 - > firstline_draw = = 2000 )
da2 - > firstline_draw = da2 - > displine ;
da2 - > lastline_draw = da2 - > displine ;
if ( da2 - > fullchange )
{
int offset = ( 8 - da2 - > scrollcache ) + 24 ;
uint32_t * p = & ( ( uint32_t * ) buffer32 - > line [ da2 - > displine ] ) [ offset ] ;
int x ;
int drawcursor ;
uint8_t chr , attr , extattr ;
int fg , bg ;
uint32_t chr_dbcs ;
int chr_wide = 0 ;
//da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc);
for ( x = 0 ; x < da2 - > hdisp ; x + = 13 )
{
chr = da2 - > vram [ ( 0x18000 + ( da2 - > ma ) ) & da2 - > vram_mask ] ;
attr = da2 - > vram [ ( ( 0x18000 + ( da2 - > ma ) ) + 1 ) & da2 - > vram_mask ] ;
extattr = da2 - > vram [ ( ( 0x10000 + ( da2 - > ma ) ) + 1 ) & da2 - > vram_mask ] ;
//if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr);
bg = attr > > 4 ;
//if (da2->blink) bg &= ~0x8;
//fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg;
fg = attr & 0xf ;
fg = IRGBtoBGRI ( fg ) ;
bg = IRGBtoBGRI ( bg ) ;
//Draw character
for ( uint32_t n = 0 ; n < 13 ; n + + ) p [ n ] = da2 - > pallook [ da2 - > egapal [ bg ] ] ; //draw blank
// SBCS or DBCS left half
if ( chr_wide = = 0 ) {
if ( extattr & 0x01 ) chr_wide = 1 ;
// Stay drawing if the char code is DBCS and not at last column.
if ( chr_wide ) {
//Get high DBCS code from the next video address
chr_dbcs = da2 - > vram [ ( 0x18000 + ( da2 - > ma ) + 2 ) & da2 - > vram_mask ] ;
chr_dbcs < < = 8 ;
chr_dbcs | = chr ;
// Get the font pattern
uint32_t font = getfont_ps55dbcs ( chr_dbcs , da2 - > sc , da2 ) ;
// Draw 13 dots
for ( uint32_t n = 0 ; n < 13 ; n + + ) {
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( font & 0x80000000 ) ? fg : bg ] ] ;
font < < = 1 ;
}
}
else {
// the char code is SBCS (ANK)
uint32_t fontbase ;
fontbase = DA2_GAIJIRAM_SBCS ;
uint16_t font = da2 - > mmio . ram [ fontbase + chr * 0x40 + da2 - > sc * 2 ] ; // w13xh29 font
font < < = 8 ;
font | = da2 - > mmio . ram [ fontbase + chr * 0x40 + da2 - > sc * 2 + 1 ] ; // w13xh29 font
//if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font);
for ( uint32_t n = 0 ; n < 13 ; n + + ) {
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( font & 0x8000 ) ? fg : bg ] ] ;
font < < = 1 ;
}
}
}
// right half of DBCS
else
{
uint32_t font = getfont_ps55dbcs ( chr_dbcs , da2 - > sc , da2 ) ;
// Draw 13 dots
for ( uint32_t n = 0 ; n < 13 ; n + + ) {
p [ n ] = da2 - > pallook [ da2 - > egapal [ ( font & 0x8000 ) ? fg : bg ] ] ;
font < < = 1 ;
}
chr_wide = 0 ;
}
//Drawing text cursor
drawcursor = ( ( da2 - > ma = = da2 - > ca ) & & da2 - > con & & da2 - > cursoron ) ;
if ( drawcursor & & da2 - > sc > = da2 - > crtc [ LC_CURSOR_ROW_START ] & & da2 - > sc < = da2 - > crtc [ LC_CURSOR_ROW_END ] )
{
//int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13);
//int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;//Choose color 2 if mode 8
//fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2;
//bg = 0;
//if (attr & 0x04) {//Color 0 if reverse
// bg = fg;
// fg = 0;
//}
for ( uint32_t n = 0 ; n < 13 ; n + + )
p [ n ] = da2 - > pallook [ da2 - > egapal [ fg ] ] ;
}
da2 - > ma + = 2 ;
p + = 13 ;
}
da2 - > ma & = da2 - > vram_display_mask ;
//da2->writelines++;
}
}
void da2_render_color_4bpp ( da2_t * da2 )
{
int changed_offset = da2 - > ma > > 12 ;
//da2_log("ma %x cf %x\n", da2->ma, changed_offset);
da2 - > plane_mask & = 0x0f ; //safety
if ( da2 - > changedvram [ changed_offset ] | | da2 - > changedvram [ changed_offset + 1 ] | | da2 - > fullchange )
{
int x ;
int offset = ( 8 - da2 - > scrollcache ) + 24 ;
uint32_t * p = & ( ( uint32_t * ) buffer32 - > line [ da2 - > displine ] ) [ offset ] ;
if ( da2 - > firstline_draw = = 2000 )
da2 - > firstline_draw = da2 - > displine ;
da2 - > lastline_draw = da2 - > displine ;
//da2_log("d %X\n", da2->ma);
for ( x = 0 ; x < = da2 - > hdisp ; x + = 8 ) //hdisp = 1024
{
uint8_t edat [ 8 ] ;
uint8_t dat ;
//get 8 pixels from vram
da2 - > ma & = da2 - > vram_display_mask ;
* ( uint32_t * ) ( & edat [ 0 ] ) = * ( uint32_t * ) ( & da2 - > vram [ da2 - > ma < < 3 ] ) ;
da2 - > ma + = 1 ;
dat = ( ( edat [ 0 ] > > 7 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 6 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 5 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 4 ) & ( 1 < < 3 ) ) ;
p [ 0 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 6 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 5 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 4 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 3 ) & ( 1 < < 3 ) ) ;
p [ 1 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 5 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 4 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 3 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 2 ) & ( 1 < < 3 ) ) ;
p [ 2 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 4 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 3 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 2 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 1 ) & ( 1 < < 3 ) ) ;
p [ 3 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 3 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 2 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 1 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 0 ) & ( 1 < < 3 ) ) ;
p [ 4 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 2 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 1 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 0 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] < < 1 ) & ( 1 < < 3 ) ) ;
p [ 5 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 1 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 0 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] < < 1 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] < < 2 ) & ( 1 < < 3 ) ) ;
p [ 6 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
dat = ( ( edat [ 0 ] > > 0 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] < < 1 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] < < 2 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] < < 3 ) & ( 1 < < 3 ) ) ;
p [ 7 ] = da2 - > pallook [ da2 - > egapal [ dat & da2 - > plane_mask ] ] ;
p + = 8 ;
}
//da2->writelines++;
}
}
void da2_render_color_8bpp ( da2_t * da2 )
{
int changed_offset = da2 - > ma > > 12 ;
//da2_log("ma %x cf %x\n", da2->ma, changed_offset);
if ( da2 - > changedvram [ changed_offset ] | | da2 - > changedvram [ changed_offset + 1 ] | | da2 - > fullchange )
{
int x ;
int offset = ( 8 - da2 - > scrollcache ) + 24 ;
uint32_t * p = & ( ( uint32_t * ) buffer32 - > line [ da2 - > displine ] ) [ offset ] ;
if ( da2 - > firstline_draw = = 2000 )
da2 - > firstline_draw = da2 - > displine ;
da2 - > lastline_draw = da2 - > displine ;
//da2_log("d %X\n", da2->ma);
for ( x = 0 ; x < = da2 - > hdisp ; x + = 8 ) //hdisp = 1024
{
uint8_t edat [ 8 ] ;
uint8_t dat ;
//get 8 pixels from vram
da2 - > ma & = da2 - > vram_display_mask ;
* ( uint32_t * ) ( & edat [ 0 ] ) = * ( uint32_t * ) ( & da2 - > vram [ da2 - > ma < < 3 ] ) ;
* ( uint32_t * ) ( & edat [ 4 ] ) = * ( uint32_t * ) ( & da2 - > vram [ ( da2 - > ma < < 3 ) + 4 ] ) ;
da2 - > ma + = 1 ;
dat = ( ( edat [ 0 ] > > 7 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 6 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 5 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 4 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] > > 3 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] > > 2 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] > > 1 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] > > 0 ) & ( 1 < < 7 ) ) ;
p [ 0 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 6 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 5 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 4 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 3 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] > > 2 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] > > 1 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] > > 0 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 1 ) & ( 1 < < 7 ) ) ;
p [ 1 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 5 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 4 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 3 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 2 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] > > 1 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] > > 0 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] < < 1 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 2 ) & ( 1 < < 7 ) ) ;
p [ 2 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 4 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 3 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 2 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 1 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] > > 0 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] < < 1 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] < < 2 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 3 ) & ( 1 < < 7 ) ) ;
p [ 3 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 3 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 2 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 1 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] > > 0 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] < < 1 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] < < 2 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] < < 3 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 4 ) & ( 1 < < 7 ) ) ;
p [ 4 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 2 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 1 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] > > 0 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] < < 1 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] < < 2 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] < < 3 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] < < 4 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 5 ) & ( 1 < < 7 ) ) ;
p [ 5 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 1 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] > > 0 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] < < 1 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] < < 2 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] < < 3 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] < < 4 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] < < 5 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 6 ) & ( 1 < < 7 ) ) ;
p [ 6 ] = da2 - > pallook [ dat ] ;
dat = ( ( edat [ 0 ] > > 0 ) & ( 1 < < 0 ) ) | ( ( edat [ 1 ] < < 1 ) & ( 1 < < 1 ) ) | ( ( edat [ 2 ] < < 2 ) & ( 1 < < 2 ) ) | ( ( edat [ 3 ] < < 3 ) & ( 1 < < 3 ) ) |
( ( edat [ 4 ] < < 4 ) & ( 1 < < 4 ) ) | ( ( edat [ 5 ] < < 5 ) & ( 1 < < 5 ) ) | ( ( edat [ 6 ] < < 6 ) & ( 1 < < 6 ) ) | ( ( edat [ 7 ] < < 7 ) & ( 1 < < 7 ) ) ;
p [ 7 ] = da2 - > pallook [ dat ] ;
p + = 8 ;
}
//da2->writelines++;
}
}
void da2_updatevidselector ( da2_t * da2 ) {
/* if VGA passthrough mode */
da2_log ( " DA2 selector: %d \n " , da2 - > ioctl [ LS_MODE ] ) ;
if ( da2 - > ioctl [ LS_MODE ] & 0x02 )
{
da2 - > override = 1 ;
svga_set_override ( da2 - > mb_vga , 0 ) ;
}
else
{
svga_set_override ( da2 - > mb_vga , 1 ) ;
da2 - > override = 0 ;
}
}
void da2_recalctimings ( da2_t * da2 )
{
double crtcconst ;
double _dispontime , _dispofftime , disptime ;
da2 - > vtotal = da2 - > crtc [ LC_VERTICAL_TOTALJ ] & 0xfff ; //w
da2 - > dispend = da2 - > crtc [ LC_V_DISPLAY_ENABLE_END ] & 0xfff ; //w
da2 - > vsyncstart = da2 - > crtc [ LC_VERTICAL_SYNC_START ] & 0xfff ; //w
da2 - > split = da2 - > crtc [ LC_LINE_COMPAREJ ] & 0xfff ; //w Line Compare
da2 - > split = 0xfff ;
da2 - > vblankstart = da2 - > crtc [ LC_START_VERTICAL_BLANK ] & 0xfff ; //w
da2 - > hdisp = da2 - > crtc [ LC_H_DISPLAY_ENABLE_END ] ;
if ( da2 - > crtc [ LC_START_H_DISPLAY_ENAB ] & 1 ) {
da2 - > hdisp - - ;
da2 - > dispend - = 29 ;
}
else {
//da2->vtotal += 2;
da2 - > dispend - - ;
//da2->vsyncstart++;
//da2->split++;
//da2->vblankstart++;
//da2->hdisp--;
}
da2 - > htotal = da2 - > crtc [ LC_HORIZONTAL_TOTAL ] ;
da2 - > htotal + = 1 ;
da2 - > rowoffset = da2 - > crtc [ LC_OFFSET ] ; //number of bytes in a scanline
da2 - > clock = da2 - > da2const ;
//da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40;
//da2->interlace = 0;
//da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b
da2 - > ca_adj = 0 ;
da2 - > rowcount = da2 - > crtc [ LC_MAXIMUM_SCAN_LINE ] ;
da2 - > hdisp_time = da2 - > hdisp ;
da2 - > render = da2_render_blank ;
//determine display mode
//if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08))
if ( da2 - > attrc [ LV_COMPATIBILITY ] & 0x08 )
{
if ( ! ( da2 - > ioctl [ LS_MODE ] & 0x01 ) ) { //16 color graphics mode
da2 - > hdisp * = 16 ;
da2 - > char_width = 13 ;
da2 - > hdisp_old = da2 - > hdisp ;
if ( da2 - > crtc [ LC_VIEWPORT_PRIORITY ] & 0x80 ) {
da2_log ( " Set videomode to PS/55 8 bpp graphics. \n " ) ;
da2 - > render = da2_render_color_8bpp ;
da2 - > vram_display_mask = DA2_MASK_GRAM ;
}
else { //PS/55 8-color
da2_log ( " Set videomode to PS/55 4 bpp graphics. \n " ) ;
da2 - > vram_display_mask = DA2_MASK_GRAM ;
da2 - > render = da2_render_color_4bpp ;
}
}
else { //text mode
if ( da2 - > attrc [ LV_ATTRIBUTE_CNTL ] & 1 ) {
da2_log ( " Set videomode to PS/55 Mode 03 text. \n " ) ;
da2 - > render = da2_render_textm3 ;
da2 - > vram_display_mask = DA2_MASK_CRAM ;
}
else { //PS/55 text(color/mono)
da2_log ( " Set videomode to PS/55 Mode 8/E text. \n " ) ;
da2 - > render = da2_render_text ;
da2 - > vram_display_mask = DA2_MASK_CRAM ;
}
da2 - > hdisp * = 13 ;
da2 - > hdisp_old = da2 - > hdisp ;
da2 - > char_width = 13 ;
}
}
else
{
da2_log ( " Set videomode to blank. \n " ) ;
}
//if (!da2->scrblank && da2->attr_palette_enable)
//{
//da2->render = da2_draw_text;
//}
// da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8);
//if (da2->recalctimings_ex)
// da2->recalctimings_ex(da2);
if ( da2 - > vblankstart < da2 - > dispend )
da2 - > dispend = da2 - > vblankstart ;
crtcconst = da2 - > clock * da2 - > char_width ;
disptime = da2 - > htotal ;
_dispontime = da2 - > hdisp_time ;
da2_log ( " Disptime %f dispontime %f hdisp %i \n " , disptime , _dispontime , da2 - > hdisp ) ;
//if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; }
_dispofftime = disptime - _dispontime ;
_dispontime * = crtcconst ;
_dispofftime * = crtcconst ;
da2 - > dispontime = ( uint64_t ) _dispontime ;
da2 - > dispofftime = ( uint64_t ) _dispofftime ;
if ( da2 - > dispontime < TIMER_USEC )
da2 - > dispontime = TIMER_USEC ;
if ( da2 - > dispofftime < TIMER_USEC )
da2 - > dispofftime = TIMER_USEC ;
da2_log ( " da2 horiz total %i display end %i vidclock %f \n " , da2 - > crtc [ 0 ] , da2 - > crtc [ 1 ] , da2 - > clock ) ;
// da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart);
// da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70);
// da2_log("da2->render %08X\n", da2->render);
}
uint8_t da2_mca_read ( int port , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
return da2 - > pos_regs [ port & 7 ] ;
}
static void da2_mapping_update ( da2_t * da2 )
{
if ( ! ( ( da2 - > pos_regs [ 2 ] ^ da2 - > old_pos2 ) & 1 ) ) return ;
da2 - > old_pos2 = da2 - > pos_regs [ 2 ] ;
//da2_recalc_mapping(da2);
if ( da2 - > pos_regs [ 2 ] & 0x01 )
{
da2_log ( " DA2 enable registers \n " ) ;
for ( int i = 0 ; i < 8 ; i + + )
da2_log ( " DA2 POS[%d]: %x \n " , i , da2 - > pos_regs [ i ] ) ;
io_sethandler ( 0x03c0 , 0x000a , da2_inb , da2_inw , NULL , da2_outb , da2_outw , NULL , da2 ) ;
io_sethandler ( 0x03e0 , 0x0010 , da2_inb , da2_inw , NULL , da2_outb , da2_outw , NULL , da2 ) ;
io_sethandler ( 0x03d0 , 0x000b , da2_in_ISR , NULL , NULL , da2_out_ISR , NULL , NULL , da2 ) ;
mem_mapping_enable ( & da2 - > cmapping ) ;
mem_mapping_enable ( & da2 - > mmio . mapping ) ;
timer_enable ( & da2 - > timer ) ;
}
else
{
da2_log ( " DA2 disable registers \n " ) ;
timer_disable ( & da2 - > timer ) ;
mem_mapping_disable ( & da2 - > cmapping ) ;
mem_mapping_disable ( & da2 - > mmio . mapping ) ;
io_removehandler ( 0x03c0 , 0x000a , da2_inb , da2_inw , NULL , da2_outb , da2_outw , NULL , da2 ) ;
io_removehandler ( 0x03e0 , 0x0010 , da2_inb , da2_inw , NULL , da2_outb , da2_outw , NULL , da2 ) ;
io_removehandler ( 0x03d0 , 0x000b , da2_in_ISR , NULL , NULL , da2_out_ISR , NULL , NULL , da2 ) ;
}
}
void da2_mca_write ( int port , uint8_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
da2_log ( " da2_mca_write: port=%04x val=%02x \n " , port , val ) ;
if ( port < 0x102 )
return ;
da2 - > pos_regs [ port & 7 ] = val ;
da2_mapping_update ( da2 ) ;
}
static uint8_t da2_mca_feedb ( void * priv )
{
const da2_t * da2 = ( da2_t * ) priv ;
return da2 - > pos_regs [ 2 ] & 0x01 ;
}
static void da2_mca_reset ( void * p )
{
da2_t * da2 = ( da2_t * ) p ;
da2_reset ( da2 ) ;
da2_mca_write ( 0x102 , 0 , da2 ) ;
}
//
static void da2_gdcropB ( uint32_t addr , da2_t * da2 ) {
for ( int i = 0 ; i < 8 ; i + + ) {
if ( da2 - > writemask & ( 1 < < i ) ) {
//da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]);
switch ( da2 - > gdcreg [ LG_COMMAND ] & 0x03 )
{
case 0 : /*Set*/
//da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]);
//da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]);
da2 - > vram [ addr | i ] = ( da2 - > gdcinput [ i ] & da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) | ( da2 - > vram [ addr | i ] & ~ da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) ;
break ;
case 1 : /*AND*/
//da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i];
da2 - > vram [ addr | i ] = ( ( da2 - > gdcinput [ i ] & da2 - > gdcsrc [ i ] ) & da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) | ( da2 - > vram [ addr | i ] & ~ da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) ;
break ;
case 2 : /*OR*/
//da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i];
da2 - > vram [ addr | i ] = ( ( da2 - > gdcinput [ i ] | da2 - > gdcsrc [ i ] ) & da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) | ( da2 - > vram [ addr | i ] & ~ da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) ;
break ;
case 3 : /*XOR*/
//da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i];
da2 - > vram [ addr | i ] = ( ( da2 - > gdcinput [ i ] ^ da2 - > gdcsrc [ i ] ) & da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) | ( da2 - > vram [ addr | i ] & ~ da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) ;
break ;
}
}
}
}
static void da2_gdcropW ( uint32_t addr , uint16_t bitmask , da2_t * da2 ) {
uint8_t bitmask_l = bitmask & 0xff ;
uint8_t bitmask_h = bitmask > > 8 ;
for ( int i = 0 ; i < 8 ; i + + ) {
if ( da2 - > writemask & ( 1 < < i ) ) {
//da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]);
switch ( da2 - > gdcreg [ LG_COMMAND ] & 0x03 )
{
case 0 : /*Set*/
//da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l);
//da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h);
da2 - > vram [ addr | i ] = ( da2 - > gdcinput [ i ] & bitmask_l ) | ( da2 - > vram [ addr | i ] & ~ bitmask_l ) ;
da2 - > vram [ ( addr + 8 ) | i ] = ( ( da2 - > gdcinput [ i ] > > 8 ) & bitmask_h )
| ( da2 - > vram [ ( addr + 8 ) | i ] & ~ bitmask_h ) ;
break ;
case 1 : /*AND*/
//da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i];
//da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8);
da2 - > vram [ addr | i ] = ( ( da2 - > gdcinput [ i ] & da2 - > gdcsrc [ i ] ) & bitmask_l ) | ( da2 - > vram [ addr | i ] & ~ bitmask_l ) ;
da2 - > vram [ ( addr + 8 ) | i ] = ( ( ( da2 - > gdcinput [ i ] > > 8 ) & ( da2 - > gdcsrc [ i ] > > 8 ) ) & bitmask_h )
| ( da2 - > vram [ ( addr + 8 ) | i ] & ~ bitmask_h ) ;
break ;
case 2 : /*OR*/
//da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i];
//da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8);
da2 - > vram [ addr | i ] = ( ( da2 - > gdcinput [ i ] | da2 - > gdcsrc [ i ] ) & bitmask_l ) | ( da2 - > vram [ addr | i ] & ~ bitmask_l ) ;
da2 - > vram [ ( addr + 8 ) | i ] = ( ( ( da2 - > gdcinput [ i ] > > 8 ) | ( da2 - > gdcsrc [ i ] > > 8 ) ) & bitmask_h )
| ( da2 - > vram [ ( addr + 8 ) | i ] & ~ bitmask_h ) ;
break ;
case 3 : /*XOR*/
//da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i];
//da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8);
da2 - > vram [ addr | i ] = ( ( da2 - > gdcinput [ i ] ^ da2 - > gdcsrc [ i ] ) & bitmask_l ) | ( da2 - > vram [ addr | i ] & ~ bitmask_l ) ;
da2 - > vram [ ( addr + 8 ) | i ] = ( ( ( da2 - > gdcinput [ i ] > > 8 ) ^ ( da2 - > gdcsrc [ i ] > > 8 ) ) & bitmask_h )
| ( da2 - > vram [ ( addr + 8 ) | i ] & ~ bitmask_h ) ;
break ;
}
}
}
}
static uint8_t da2_mmio_read ( uint32_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
addr & = DA2_MASK_MMIO ;
if ( da2 - > ioctl [ LS_MMIO ] & 0x10 ) {
if ( da2 - > fctl [ LF_MMIO_SEL ] = = 0x80 )
//linear access
addr | = ( ( uint32_t ) da2 - > fctl [ LF_MMIO_ADDR ] < < 17 ) ;
else
{
//64k bank switch access
uint32_t index = da2 - > fctl [ LF_MMIO_MODE ] & 0x0f ;
index < < = 8 ;
index | = da2 - > fctl [ LF_MMIO_ADDR ] ;
addr + = index * 0x40 ;
}
//da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr);
switch ( da2 - > fctl [ LF_MMIO_MODE ] & 0xf0 ) {
case 0xb0 : //Gaiji RAM
addr & = DA2_MASK_GAIJIRAM ; //safety access
//da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]);
return da2 - > mmio . ram [ addr ] ;
break ;
case 0x10 : //Font ROM
if ( da2 - > mmio . charset = = DA2_DCONFIG_CHARSET_HANT ) {
if ( addr > = 0x1a0000 ) return DA2_INVALIDACCESS8 ;
if ( addr > = 0x180000 ) addr - = 0x40000 ; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range,
but the Chinese font sub card actually has this alias , and is used by DOS T5 .0 . */
}
if ( addr > = DA2_FONTROM_SIZE ) return DA2_INVALIDACCESS8 ;
//da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]);
return da2 - > mmio . font [ addr ] ;
break ;
default :
return DA2_INVALIDACCESS8 ; //invalid memory access
break ;
}
}
else if ( ! ( da2 - > ioctl [ LS_MODE ] & 1 ) ) //8 or 256 color mode
{
cycles - = video_timing_read_b ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcla [ i ] = da2 - > vram [ ( addr < < 3 ) | i ] ; //read in byte
//da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]);
if ( da2 - > gdcreg [ LG_MODE ] & 0x08 ) { //compare data across planes if the read mode bit (3EB 05, bit 3) is 1
uint8_t ret = 0 ;
for ( int i = 0 ; i < 8 ; i + + )
{
if ( ~ da2 - > gdcreg [ LG_COLOR_DONT_CARE ] & ( 1 < < i ) ) //color don't care register
ret | = da2 - > gdcla [ i ] ^ ( ( da2 - > gdcreg [ LG_COLOR_COMPAREJ ] & ( 1 < < i ) ) ? 0xff : 0 ) ;
}
return ~ ret ;
}
else return da2 - > gdcla [ da2 - > readplane ] ;
}
else //text mode 3
{
cycles - = video_timing_read_b ;
return da2 - > vram [ addr ] ;
}
}
static uint16_t da2_mmio_readw ( uint32_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
da2_log ( " da2_readW: %x %x %x %x %x \n " , da2 - > ioctl [ LS_MMIO ] , da2 - > fctl [ LF_MMIO_SEL ] , da2 - > fctl [ LF_MMIO_MODE ] , da2 - > fctl [ LF_MMIO_ADDR ] , addr ) ;
if ( da2 - > ioctl [ LS_MMIO ] & 0x10 ) {
return ( uint16_t ) da2_mmio_read ( addr , da2 ) | ( uint16_t ) ( da2_mmio_read ( addr + 1 , da2 ) < < 8 ) ;
}
else if ( ! ( da2 - > ioctl [ LS_MODE ] & 1 ) ) //8 color or 256 color mode
{
cycles - = video_timing_read_w ;
addr & = DA2_MASK_MMIO ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcla [ i ] = ( uint16_t ) ( da2 - > vram [ ( addr < < 3 ) | i ] ) | ( ( uint16_t ) ( da2 - > vram [ ( ( addr < < 3 ) + 8 ) | i ] ) < < 8 ) ; //read vram into latch
# ifdef ENABLE_DA2_DEBUGBLT
////debug
//if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr)
//{
// fprintf(da2->mmrdbg_fp, "\nR %x ", addr);
// for (int i = 0; i <= 0xb; i++)
// fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]);
//}
//for (int i = 0; i < 16; i++)
//{
// int pixeldata = 0;
// if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1;
// fprintf(da2->mmrdbg_fp, "%X", pixeldata);
//}
//da2->mmrdbg_vidaddr = addr;
# endif
if ( da2 - > gdcreg [ LG_MODE ] & 0x08 ) { //compare data across planes if the read mode bit (3EB 05, bit 3) is 1
uint16_t ret = 0 ;
for ( int i = 0 ; i < 8 ; i + + )
{
if ( ~ da2 - > gdcreg [ LG_COLOR_DONT_CARE ] & ( 1 < < i ) ) //color don't care register
ret | = da2 - > gdcla [ i ] ^ ( ( da2 - > gdcreg [ LG_COLOR_COMPAREJ ] & ( 1 < < i ) ) ? 0xffff : 0 ) ;
}
return ~ ret ;
}
else
{
//da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]);
return da2 - > gdcla [ da2 - > readplane ] ;
}
}
else {
return ( uint16_t ) da2_mmio_read ( addr , da2 ) | ( uint16_t ) ( da2_mmio_read ( addr + 1 , da2 ) < < 8 ) ;
}
}
static void da2_mmio_write ( uint32_t addr , uint8_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
//da2_log("da2_mmio_write %x %x\n", addr, val);
if ( ( addr & ~ DA2_MASK_MMIO ) ! = 0xA0000 ) return ;
addr & = DA2_MASK_MMIO ;
if ( da2 - > ioctl [ LS_MMIO ] & 0x10 ) {
//if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI);
//Gaiji RAM
if ( da2 - > fctl [ LF_MMIO_SEL ] = = 0x80 )
addr | = ( ( uint32_t ) da2 - > fctl [ LF_MMIO_ADDR ] < < 17 ) ; //xxxy yyyy yyyy yyyy yyyy
else
{
uint32_t index = da2 - > fctl [ LF_MMIO_MODE ] & 0x0f ;
index < < = 8 ;
index | = da2 - > fctl [ LF_MMIO_ADDR ] ;
addr + = index * 0x40 ;
}
switch ( da2 - > fctl [ LF_MMIO_MODE ] ) {
case 0xb0 : //Gaiji RAM 1011 0000
addr & = DA2_MASK_GAIJIRAM ; //safety access
da2 - > mmio . ram [ addr ] = val ;
break ;
case 0x10 : //Font ROM 0001 0000
//Read-Only
break ;
case 0x00 :
//da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc);
//addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx
//if (addr >= DA2_BLT_MEMSIZE)
//{
// da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val);
// return;
//}
da2 - > bitblt . indata = 1 ;
if ( da2 - > bitblt . payload_addr > = DA2_BLT_MEMSIZE )
da2_log ( " da2_mmio_write payload overflow! mem %x, addr %x, val %x \n " , da2 - > fctl [ LF_MMIO_MODE ] , addr , val ) ;
da2 - > bitblt . payload [ da2 - > bitblt . payload_addr ] = val ;
da2 - > bitblt . payload_addr + + ;
break ;
default :
da2_log ( " da2_mmio_write failed mem %x, addr %x, val %x \n " , da2 - > fctl [ LF_MMIO_MODE ] , addr , val ) ;
break ;
}
}
else if ( ! ( da2 - > ioctl [ LS_MODE ] & 1 ) ) //8 color or 256 color mode
{
uint8_t wm = da2 - > writemask ;
//da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val);
# ifdef ENABLE_DA2_DEBUGBLT
//debug
//if (!(da2->gdcreg[LG_COMMAND] & 0x08))
//{
if ( ( ( int ) addr - ( int ) da2 - > mmdbg_vidaddr ) > 2 | | ( ( ( int ) da2 - > mmdbg_vidaddr - ( int ) addr ) > 2 ) | | da2 - > mmdbg_vidaddr = = addr )
{
fprintf ( da2 - > mmdbg_fp , " \n B %x " , addr ) ;
for ( int i = 0 ; i < = 0xb ; i + + )
fprintf ( da2 - > mmdbg_fp , " %02x " , da2 - > gdcreg [ i ] ) ;
}
for ( int i = 0 ; i < 8 ; i + + )
{
int pixeldata = 0 ;
if ( val & ( 1 < < ( 7 - i ) ) ) pixeldata = ( da2 - > writemask & 0xf ) ;
fprintf ( da2 - > mmdbg_fp , " %X " , pixeldata ) ;
}
da2 - > mmdbg_vidaddr = addr ;
//}
# endif
cycles - = video_timing_write_b ;
da2 - > changedvram [ addr > > 12 ] = changeframecount ;
addr < < = 3 ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcsrc [ i ] = da2 - > gdcla [ i ] ; //use latch
//da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc);
//da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]);
if ( ! ( da2 - > gdcreg [ LG_COMMAND ] & 0x08 ) )
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > gdcreg [ LG_ENABLE_SRJ ] & ( 1 < < i ) ) da2 - > gdcinput [ i ] = ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) ? 0xff : 0 ;
else if ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) da2 - > gdcinput [ i ] = ~ val ;
else da2 - > gdcinput [ i ] = val ;
da2_gdcropB ( addr , da2 ) ;
return ;
}
switch ( da2 - > writemode )
{
case 2 :
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > writemask & ( 1 < < i ) ) da2 - > vram [ addr | i ] = da2 - > gdcsrc [ i ] ;
break ;
case 0 :
if ( da2 - > gdcreg [ LG_DATA_ROTATION ] & 7 )
val = svga_rotate [ da2 - > gdcreg [ LG_DATA_ROTATION ] & 7 ] [ val ] ;
if ( da2 - > gdcreg [ LG_BIT_MASK_LOW ] = = 0xff & & ! ( da2 - > gdcreg [ LG_COMMAND ] & 0x03 ) & & ( ! da2 - > gdcreg [ LG_ENABLE_SRJ ] ) )
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > writemask & ( 1 < < i ) ) da2 - > vram [ addr | i ] = val ;
}
else
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > gdcreg [ LG_ENABLE_SRJ ] & ( 1 < < i ) ) da2 - > gdcinput [ i ] = ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) ? 0xff : 0 ;
else da2 - > gdcinput [ i ] = val ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > debug_vramold [ i ] = da2 - > vram [ addr | i ] ; //use latch
da2_gdcropB ( addr , da2 ) ;
//for (int i = 0; i < 8; i++)
// da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch
//// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
}
break ;
case 1 :
if ( ! ( da2 - > gdcreg [ LG_COMMAND ] & 0x03 ) & & ( ! da2 - > gdcreg [ LG_ENABLE_SRJ ] ) )
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > writemask & ( 1 < < i ) ) da2 - > vram [ addr | i ] = ( ( ( val & ( 1 < < i ) ) ? 0xff : 0 ) & da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) | ( da2 - > gdcsrc [ i ] & ~ da2 - > gdcreg [ LG_BIT_MASK_LOW ] ) ;
}
else
{
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcinput [ i ] = ( ( val & ( 1 < < i ) ) ? 0xff : 0 ) ;
da2_gdcropB ( addr , da2 ) ;
}
break ;
case 3 :
if ( da2 - > gdcreg [ LG_DATA_ROTATION ] & 7 )
val = svga_rotate [ da2 - > gdcreg [ LG_DATA_ROTATION ] & 7 ] [ val ] ;
wm = da2 - > gdcreg [ LG_BIT_MASK_LOW ] ;
da2 - > gdcreg [ LG_BIT_MASK_LOW ] & = val ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcinput [ i ] = ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) ? 0xff : 0 ;
da2_gdcropB ( addr , da2 ) ;
da2 - > gdcreg [ LG_BIT_MASK_LOW ] = wm ;
break ;
}
//da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]);
}
else // mode 3h text
{
cycles - = video_timing_write_b ;
da2 - > vram [ addr ] = val ;
da2 - > fullchange = 2 ;
}
}
uint16_t rightRotate ( uint16_t data , uint8_t count )
{
return ( data > > count ) | ( data < < ( sizeof ( data ) * 8 - count ) ) ;
}
static void da2_mmio_gc_writeW ( uint32_t addr , uint16_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
uint8_t wm = da2 - > writemask ;
uint16_t bitmask = da2 - > gdcreg [ LG_BIT_MASK_HIGH ] ;
bitmask < < = 8 ;
bitmask | = ( uint16_t ) da2 - > gdcreg [ LG_BIT_MASK_LOW ] ;
# ifdef ENABLE_DA2_DEBUGBLT
//debug
//if (!(da2->gdcreg[LG_COMMAND] & 0x08))
//{
if ( ( ( int ) addr - ( int ) da2 - > mmdbg_vidaddr ) > 2 | | ( ( ( int ) da2 - > mmdbg_vidaddr - ( int ) addr ) > 2 ) | | da2 - > mmdbg_vidaddr = = addr )
{
fprintf ( da2 - > mmdbg_fp , " \n W %x " , addr ) ;
for ( int i = 0 ; i < = 0xb ; i + + )
fprintf ( da2 - > mmdbg_fp , " %02x " , da2 - > gdcreg [ i ] ) ;
}
for ( int i = 0 ; i < 16 ; i + + )
{
int pixeldata = 0 ;
if ( val & ( 1 < < ( 15 - i ) ) ) pixeldata = ( da2 - > writemask & 0xf ) ;
fprintf ( da2 - > mmdbg_fp , " %X " , pixeldata ) ;
}
da2 - > mmdbg_vidaddr = addr ;
//}
# endif
cycles - = video_timing_write_w ;
//cycles_lost += video_timing_write_w;
//da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val);
//da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI);
da2 - > changedvram [ addr > > 12 ] = changeframecount ;
da2 - > changedvram [ ( addr + 1 ) > > 12 ] = changeframecount ;
addr < < = 3 ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcsrc [ i ] = da2 - > gdcla [ i ] ; //use latch
if ( ! ( da2 - > gdcreg [ LG_COMMAND ] & 0x08 ) )
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > gdcreg [ LG_ENABLE_SRJ ] & ( 1 < < i ) ) da2 - > gdcinput [ i ] = ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) ? 0xffff : 0 ;
else if ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) da2 - > gdcinput [ i ] = ~ val ;
else da2 - > gdcinput [ i ] = val ;
da2_gdcropW ( addr , bitmask , da2 ) ;
return ;
}
//da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]
// , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]);
switch ( da2 - > writemode )
{
case 2 :
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > writemask & ( 1 < < i ) )
{
da2 - > vram [ addr | i ] = da2 - > gdcsrc [ i ] & 0xff ;
da2 - > vram [ ( addr + 8 ) | i ] = da2 - > gdcsrc [ i ] > > 8 ;
}
break ;
case 0 :
if ( da2 - > gdcreg [ LG_DATA_ROTATION ] & 15 )
val = rightRotate ( val , da2 - > gdcreg [ LG_DATA_ROTATION ] & 15 ) ; //val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work
if ( bitmask = = 0xffff & & ! ( da2 - > gdcreg [ LG_COMMAND ] & 0x03 ) & & ( ! da2 - > gdcreg [ LG_ENABLE_SRJ ] ) )
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > writemask & ( 1 < < i ) )
{
da2 - > vram [ addr | i ] = val & 0xff ;
da2 - > vram [ ( addr + 8 ) | i ] = val > > 8 ;
}
}
else
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > gdcreg [ LG_ENABLE_SRJ ] & ( 1 < < i ) ) da2 - > gdcinput [ i ] = ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) ? 0xffff : 0 ;
else da2 - > gdcinput [ i ] = val ;
da2_gdcropW ( addr , bitmask , da2 ) ;
// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
}
break ;
case 1 :
if ( ! ( da2 - > gdcreg [ LG_COMMAND ] & 0x03 ) & & ( ! da2 - > gdcreg [ LG_ENABLE_SRJ ] ) )
{
for ( int i = 0 ; i < 8 ; i + + )
if ( da2 - > writemask & ( 1 < < i ) )
{
uint16_t wdata = ( ( ( val & ( 1 < < i ) ) ? 0xffff : 0 ) & bitmask ) | ( da2 - > gdcsrc [ i ] & ~ bitmask ) ;
da2 - > vram [ addr | i ] = wdata & 0xff ;
da2 - > vram [ ( addr + 8 ) | i ] = wdata > > 8 ;
}
}
else
{
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcinput [ i ] = ( ( val & ( 1 < < i ) ) ? 0xffff : 0 ) ;
da2_gdcropW ( addr , bitmask , da2 ) ;
}
break ;
case 3 :
if ( da2 - > gdcreg [ LG_DATA_ROTATION ] & 15 )
val = rightRotate ( val , da2 - > gdcreg [ LG_DATA_ROTATION ] & 15 ) ; //val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work
wm = bitmask ;
bitmask & = val ;
for ( int i = 0 ; i < 8 ; i + + )
da2 - > gdcinput [ i ] = ( da2 - > gdcreg [ LG_SET_RESETJ ] & ( 1 < < i ) ) ? 0xffff : 0 ;
da2_gdcropW ( addr , bitmask , da2 ) ;
bitmask = wm ;
break ;
}
//da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]
// , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]);
}
static void da2_mmio_writew ( uint32_t addr , uint16_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
//if ((addr & ~0x1ffff) != 0xA0000) return;
if ( da2 - > ioctl [ LS_MMIO ] & 0x10 ) {
//da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
da2_mmio_write ( addr , val & 0xff , da2 ) ;
da2_mmio_write ( addr + 1 , val > > 8 , da2 ) ;
}
else if ( ! ( da2 - > ioctl [ LS_MODE ] & 1 ) ) //8 color or 256 color mode
{
addr & = DA2_MASK_MMIO ;
//return;
//da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
da2_mmio_gc_writeW ( addr , val , da2 ) ;
}
else { //mode 3h text
//if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc);
//da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val);
da2_mmio_write ( addr , val & 0xff , da2 ) ;
da2_mmio_write ( addr + 1 , val > > 8 , da2 ) ;
}
}
static void da2_code_write ( uint32_t addr , uint8_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
//if ((addr & ~0xfff) != 0xE0000) return;
addr & = DA2_MASK_CRAM ;
da2 - > cram [ addr ] = val ;
da2 - > fullchange = 2 ;
}
static void da2_code_writeb ( uint32_t addr , uint8_t val , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
//da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val);
cycles - = video_timing_write_b ;
da2_code_write ( addr , val , da2 ) ;
}
static void da2_code_writew ( uint32_t addr , uint16_t val , void * p )
{
//da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val);
da2_t * da2 = ( da2_t * ) p ;
cycles - = video_timing_write_w ;
da2_code_write ( addr , val & 0xff , da2 ) ;
da2_code_write ( addr + 1 , val > > 8 , da2 ) ;
}
static uint8_t da2_code_read ( uint32_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
if ( ( addr & ~ DA2_MASK_CRAM ) ! = 0xE0000 ) return DA2_INVALIDACCESS8 ;
addr & = DA2_MASK_CRAM ;
return da2 - > cram [ addr ] ;
}
static uint8_t da2_code_readb ( uint32_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
cycles - = video_timing_read_b ;
return da2_code_read ( addr , da2 ) ;
}
static uint16_t da2_code_readw ( uint32_t addr , void * p )
{
da2_t * da2 = ( da2_t * ) p ;
cycles - = video_timing_read_w ;
return da2_code_read ( addr , da2 ) | ( da2_code_read ( addr + 1 , da2 ) < < 8 ) ;
//return 0;
}
void da2_doblit ( int y1 , int y2 , int wx , int wy , da2_t * da2 )
{
if ( wx ! = xsize | | wy ! = ysize ) {
xsize = wx ;
ysize = wy ;
set_screen_size ( xsize , ysize ) ;
if ( video_force_resize_get ( ) )
video_force_resize_set ( 0 ) ;
}
video_blit_memtoscreen ( 32 , 0 , xsize , ysize ) ;
frames + + ;
video_res_x = wx ;
video_res_y = wy ;
video_bpp = 8 ;
}
void da2_poll ( void * priv )
{
da2_t * da2 = ( da2_t * ) priv ;
int x ;
if ( ! da2 - > linepos )
{
timer_advance_u64 ( & da2 - > timer , da2 - > dispofftime ) ;
// if (output) printf("Display off %f\n",vidtime);
da2 - > cgastat | = 1 ;
da2 - > linepos = 1 ;
if ( da2 - > dispon )
{
da2 - > hdisp_on = 1 ;
da2 - > ma & = da2 - > vram_display_mask ;
if ( da2 - > firstline = = 2000 )
{
da2 - > firstline = da2 - > displine ;
video_wait_for_buffer ( ) ;
}
if ( ! da2 - > override )
da2 - > render ( da2 ) ;
if ( da2 - > lastline < da2 - > displine )
da2 - > lastline = da2 - > displine ;
}
//da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask);
da2 - > displine + + ;
//if (da2->interlace)
// da2->displine++;
if ( ( da2 - > cgastat & 8 ) & & ( ( da2 - > displine & 0xf ) = = ( da2 - > crtc [ LC_VERTICAL_SYNC_END ] & 0xf ) ) & & da2 - > vslines )
{
//da2_log("Vsync off at line %i\n",displine);
da2 - > cgastat & = ~ 8 ;
}
da2 - > vslines + + ;
if ( da2 - > displine > 1200 )
da2 - > displine = 0 ;
// da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322],
// displine, vc, ma);
}
else
{
// da2_log("VC %i ma %05X\n", da2->vc, da2->ma);
timer_advance_u64 ( & da2 - > timer , da2 - > dispontime ) ;
// if (output) printf("Display on %f\n",vidtime);
if ( da2 - > dispon )
da2 - > cgastat & = ~ 1 ;
da2 - > hdisp_on = 0 ;
da2 - > linepos = 0 ;
if ( da2 - > sc = = ( da2 - > crtc [ LC_CURSOR_ROW_END ] & 31 ) )
da2 - > con = 0 ;
if ( da2 - > dispon )
{
if ( da2 - > sc = = da2 - > rowcount )
{
da2 - > linecountff = 0 ;
da2 - > sc = 0 ;
da2 - > maback + = ( da2 - > rowoffset < < 1 ) ; // color = 0x50(80), mono = 0x40(64)
if ( da2 - > interlace )
da2 - > maback + = ( da2 - > rowoffset < < 1 ) ;
da2 - > maback & = da2 - > vram_display_mask ;
da2 - > ma = da2 - > maback ;
}
else
{
da2 - > sc + + ;
da2 - > sc & = 31 ;
da2 - > ma = da2 - > maback ;
}
}
da2 - > vc + + ;
da2 - > vc & = 2047 ;
if ( da2 - > vc = = da2 - > dispend )
{
da2 - > dispon = 0 ;
//if (da2->crtc[10] & 0x20) da2->cursoron = 0;
//else da2->cursoron = da2->blink & 16;
if ( da2 - > ioctl [ LS_MODE ] & 1 ) { //in text mode
if ( da2 - > attrc [ LV_CURSOR_CONTROL ] & 0x01 ) //cursor blinking
{
da2 - > cursoron = ( da2 - > blink | 1 ) & da2 - > blinkconf ;
}
else
{
da2 - > cursoron = 0 ;
}
if ( ! ( da2 - > blink & ( 0x10 - 1 ) ) ) //force redrawing for cursor and blink attribute
da2 - > fullchange = 2 ;
}
da2 - > blink + + ;
for ( x = 0 ; x < ( ( da2 - > vram_mask + 1 ) > > 12 ) ; x + + )
{
if ( da2 - > changedvram [ x ] )
da2 - > changedvram [ x ] - - ;
}
// memset(changedvram,0,2048); del
if ( da2 - > fullchange )
{
da2 - > fullchange - - ;
}
}
if ( da2 - > vc = = da2 - > vsyncstart )
{
int wx , wy ;
// da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw);
da2 - > dispon = 0 ;
da2 - > cgastat | = 8 ;
x = da2 - > hdisp ;
//if (da2->interlace && !da2->oddeven) da2->lastline++;
//if (da2->interlace && da2->oddeven) da2->firstline--;
wx = x ;
wy = da2 - > lastline - da2 - > firstline ;
da2_doblit ( da2 - > firstline_draw , da2 - > lastline_draw + 1 , wx , wy , da2 ) ;
da2 - > firstline = 2000 ;
da2 - > lastline = 0 ;
da2 - > firstline_draw = 2000 ;
da2 - > lastline_draw = 0 ;
da2 - > oddeven ^ = 1 ;
changeframecount = da2 - > interlace ? 3 : 2 ;
da2 - > vslines = 0 ;
//if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5);
//else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5);
//da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj;
/* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch;
else */ da2 - > ma = da2 - > maback = da2 - > ma_latch ;
da2 - > ca = ( ( da2 - > crtc [ LC_CURSOR_LOC_HIGH ] < < 8 ) | da2 - > crtc [ LC_CURSOR_LOC_LOWJ ] ) + da2 - > ca_adj ;
da2 - > ma < < = 1 ;
da2 - > maback < < = 1 ;
da2 - > ca < < = 1 ;
// da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven);
}
if ( da2 - > vc = = da2 - > vtotal )
{
// da2_log("VC vtotal\n");
// printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend);
da2 - > vc = 0 ;
da2 - > sc = da2 - > crtc [ LC_PRESET_ROW_SCANJ ] & 0x1f ;
da2 - > dispon = 1 ;
da2 - > displine = ( da2 - > interlace & & da2 - > oddeven ) ? 1 : 0 ;
da2 - > scrollcache = da2 - > attrc [ LV_PANNING ] & 7 ;
}
if ( da2 - > sc = = ( da2 - > crtc [ LC_CURSOR_ROW_START ] & 31 ) )
da2 - > con = 1 ;
}
// printf("2 %i\n",da2_vsyncstart);
//da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc);
//da2_log("r");
}
static void da2_loadfont ( char * fname , void * p ) {
da2_t * da2 = ( da2_t * ) p ;
uint8_t buf ;
//uint32_t code = 0;
uint64_t fsize ;
if ( ! fname ) return ;
if ( * fname = = ' \0 ' ) return ;
FILE * mfile = rom_fopen ( fname , " rb " ) ;
if ( ! mfile ) {
//da2_log("MSG: Can't open binary ROM font file: %s\n", fname);
return ;
}
fseek ( mfile , 0 , SEEK_END ) ;
fsize = ftell ( mfile ) ; //get filesize
fseek ( mfile , 0 , SEEK_SET ) ;
if ( fsize > DA2_FONTROM_SIZE ) {
fsize = DA2_FONTROM_SIZE ; //truncate read data
//da2_log("MSG: The binary ROM font is truncated: %s\n", fname);
//fclose(mfile);
//return 1;
}
uint32_t j = 0 ;
while ( ftell ( mfile ) < fsize ) {
fread ( & buf , sizeof ( uint8_t ) , 1 , mfile ) ;
da2 - > mmio . font [ j ] = buf ;
j + + ;
}
fclose ( mfile ) ;
return ;
}
/* 12-bit DAC color palette for IBMJ Display Adapter with color monitor */
static uint8_t ps55_palette_color [ 64 ] [ 3 ] =
{
{ 0x00 , 0x00 , 0x00 } , { 0x00 , 0x00 , 0x2A } , { 0x00 , 0x2A , 0x00 } , { 0x00 , 0x2A , 0x2A } , { 0x2A , 0x00 , 0x00 } , { 0x2A , 0x00 , 0x2A } , { 0x2A , 0x2A , 0x00 } , { 0x2A , 0x2A , 0x2A } ,
{ 0x00 , 0x00 , 0x15 } , { 0x00 , 0x00 , 0x3F } , { 0x00 , 0x2A , 0x15 } , { 0x00 , 0x2A , 0x3F } , { 0x2A , 0x00 , 0x15 } , { 0x2A , 0x00 , 0x3F } , { 0x2A , 0x2A , 0x15 } , { 0x2A , 0x2A , 0x3F } ,
{ 0x00 , 0x15 , 0x00 } , { 0x00 , 0x15 , 0x2A } , { 0x00 , 0x3F , 0x00 } , { 0x00 , 0x3F , 0x2A } , { 0x2A , 0x15 , 0x00 } , { 0x2A , 0x15 , 0x2A } , { 0x2A , 0x3F , 0x00 } , { 0x2A , 0x3F , 0x2A } ,
{ 0x00 , 0x15 , 0x15 } , { 0x00 , 0x15 , 0x3F } , { 0x00 , 0x3F , 0x15 } , { 0x00 , 0x3F , 0x3F } , { 0x2A , 0x15 , 0x15 } , { 0x2A , 0x15 , 0x3F } , { 0x2A , 0x3F , 0x15 } , { 0x2A , 0x3F , 0x3F } ,
{ 0x15 , 0x00 , 0x00 } , { 0x15 , 0x00 , 0x2A } , { 0x15 , 0x2A , 0x00 } , { 0x15 , 0x2A , 0x2A } , { 0x3F , 0x00 , 0x00 } , { 0x3F , 0x00 , 0x2A } , { 0x3F , 0x2A , 0x00 } , { 0x3F , 0x2A , 0x2A } ,
{ 0x15 , 0x00 , 0x15 } , { 0x15 , 0x00 , 0x3F } , { 0x15 , 0x2A , 0x15 } , { 0x15 , 0x2A , 0x3F } , { 0x3F , 0x00 , 0x15 } , { 0x3F , 0x00 , 0x3F } , { 0x3F , 0x2A , 0x15 } , { 0x3F , 0x2A , 0x3F } ,
{ 0x15 , 0x15 , 0x00 } , { 0x15 , 0x15 , 0x2A } , { 0x15 , 0x3F , 0x00 } , { 0x15 , 0x3F , 0x2A } , { 0x3F , 0x15 , 0x00 } , { 0x3F , 0x15 , 0x2A } , { 0x3F , 0x3F , 0x00 } , { 0x3F , 0x3F , 0x2A } ,
{ 0x15 , 0x15 , 0x15 } , { 0x15 , 0x15 , 0x3F } , { 0x15 , 0x3F , 0x15 } , { 0x15 , 0x3F , 0x3F } , { 0x3F , 0x15 , 0x15 } , { 0x3F , 0x15 , 0x3F } , { 0x3F , 0x3F , 0x15 } , { 0x3F , 0x3F , 0x3F }
} ;
void da2_reset_ioctl ( da2_t * da2 )
{
da2 - > ioctl [ LS_RESET ] = 0x00 ; /* Bit 0: Reset sequencer */
da2_outw ( LS_INDEX , 0x0302 , da2 ) ; /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */
da2_outw ( LS_INDEX , 0x0008 , da2 ) ; /* Index 08, Bit 0: Enable MMIO */
}
static void
da2_reset ( void * priv )
{
da2_t * da2 = ( da2_t * ) priv ;
/* Initialize drawing */
da2 - > bitblt . exec = DA2_BLT_CIDLE ;
da2 - > render = da2_render_blank ;
da2_reset_ioctl ( da2 ) ;
da2 - > pos_regs [ 0 ] = DA2_POSID_L ; /* Adapter Identification Byte (Low byte) */
da2 - > pos_regs [ 1 ] = DA2_POSID_H ; /* Adapter Identification Byte (High byte) */
da2 - > pos_regs [ 2 ] = 0x40 ; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */
da2 - > ioctl [ LS_CONFIG1 ] = OldLSI | Page_Two ; /* Configuration 1 : DA-II, 1024 KB */
da2 - > ioctl [ LS_CONFIG1 ] | = ( ( da2 - > monitorid & 0x8 ) < < 1 ) ; /* Configuration 1 : Monitor ID 3 */
da2 - > ioctl [ LS_CONFIG2 ] = ( da2 - > monitorid & 0x7 ) ; /* Configuration 2: Monitor ID 0-2 */
da2 - > fctl [ 0 ] = 0x2b ; /* 3E3h:0 */
da2 - > fctl [ LF_MMIO_MODE ] = 0xb0 ; /* 3E3h:0bh */
da2 - > attrc [ LV_CURSOR_COLOR ] = 0x0f ; /* cursor color */
da2 - > crtc [ LC_HORIZONTAL_TOTAL ] = 63 ; /* Horizontal Total */
da2 - > crtc [ LC_VERTICAL_TOTALJ ] = 255 ; /* Vertical Total (These two must be set before the timer starts.) */
da2 - > ma_latch = 0 ;
da2 - > interlace = 0 ;
da2 - > attrc [ LV_CURSOR_CONTROL ] = 0x13 ; /* cursor options */
da2 - > attr_palette_enable = 0 ; /* disable attribute generator */
/* Set default color palette (Windows 3.1 display driver won't reset palette) */
da2_out ( 0x3c8 , 0 , da2 ) ;
for ( int i = 0 ; i < 256 ; i + + ) {
da2_out ( 0x3c9 , ps55_palette_color [ i & 0x3F ] [ 0 ] , da2 ) ;
da2_out ( 0x3c9 , ps55_palette_color [ i & 0x3F ] [ 1 ] , da2 ) ;
da2_out ( 0x3c9 , ps55_palette_color [ i & 0x3F ] [ 2 ] , da2 ) ;
}
}
static void * da2_init ( )
{
//Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM
if ( svga_get_pri ( ) = = NULL )
return NULL ;
svga_t * mb_vga = svga_get_pri ( ) ;
mb_vga - > cable_connected = 0 ;
da2_t * da2 = malloc ( sizeof ( da2_t ) ) ;
da2 - > mb_vga = mb_vga ;
da2 - > dispontime = 1000ull < < 32 ;
da2 - > dispofftime = 1000ull < < 32 ;
int memsize = 1024 * 1024 ;
da2 - > vram = malloc ( memsize ) ;
da2 - > vram_mask = memsize - 1 ;
da2 - > cram = malloc ( 0x1000 ) ;
da2 - > vram_display_mask = DA2_MASK_CRAM ;
da2 - > changedvram = malloc ( /*(memsize >> 12) << 1*/ 0x1000000 > > 12 ) ; //XX000h
da2 - > monitorid = device_get_config_int ( " montype " ) ; /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */
da2 - > mmio . charset = device_get_config_int ( " charset " ) ;
da2 - > mmio . font = malloc ( DA2_FONTROM_SIZE ) ;
switch ( da2 - > mmio . charset )
{
case DA2_DCONFIG_CHARSET_HANT :
da2_loadfont ( DA2_FONTROM_PATH_HANT , da2 ) ;
break ;
case DA2_DCONFIG_CHARSET_JPAN :
da2_loadfont ( DA2_FONTROM_PATH_JPAN , da2 ) ;
break ;
}
mca_add ( da2_mca_read , da2_mca_write , da2_mca_feedb , da2_mca_reset , da2 ) ;
da2 - > da2const = ( uint64_t ) ( ( cpuclock / DA2_PIXELCLOCK ) * ( float ) ( 1ull < < 32 ) ) ;
memset ( da2 - > bitblt . payload , 0x00 , DA2_BLT_MEMSIZE ) ;
memset ( da2 - > bitblt . reg , 0xfe , DA2_BLT_REGSIZE * sizeof ( uint32_t ) ) ; /* clear memory */
# ifdef ENABLE_DA2_DEBUGBLT
da2 - > bitblt . debug_reg = malloc ( DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE ) ;
da2 - > mmdbg_fp = fopen ( " da2_mmiowdat.txt " , " w " ) ;
da2 - > mmrdbg_fp = fopen ( " da2_mmiordat.txt " , " w " ) ;
da2 - > bitblt . debug_reg_ip = 0 ;
# endif
da2 - > bitblt . payload_addr = 0 ;
da2_reset ( da2 ) ;
mem_mapping_add ( & da2 - > mmio . mapping , 0xA0000 , 0x20000 , da2_mmio_read , da2_mmio_readw , NULL , da2_mmio_write , da2_mmio_writew , NULL , NULL , MEM_MAPPING_EXTERNAL , da2 ) ;
//da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size);
mem_mapping_disable ( & da2 - > mmio . mapping ) ;
mem_mapping_add ( & da2 - > cmapping , 0xE0000 , 0x1000 , da2_code_readb , da2_code_readw , NULL , da2_code_writeb , da2_code_writew , NULL , NULL , MEM_MAPPING_EXTERNAL , da2 ) ;
mem_mapping_disable ( & da2 - > cmapping ) ;
timer_add ( & da2 - > timer , da2_poll , da2 , 0 ) ;
da2 - > bitblt . timerspeed = 1 * TIMER_USEC ; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */
timer_add ( & da2 - > bitblt . timer , da2_bitblt_exec , da2 , 0 ) ;
return da2 ;
}
static int da2_available ( )
{
return ( rom_present ( DA2_FONTROM_PATH_HANT ) | | rom_present ( DA2_FONTROM_PATH_JPAN ) ) ;
}
void da2_close ( void * p )
{
da2_t * da2 = ( da2_t * ) p ;
/* dump mem for debug */
2025-02-15 11:05:16 +09:00
# ifdef ENABLE_DA2_LOG
2025-02-15 08:27:17 +09:00
FILE * f ;
f = fopen ( " da2_cram.dmp " , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( da2 - > cram , 0x1000 , 1 , f ) ;
fclose ( f ) ;
}
f = fopen ( " da2_vram.dmp " , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( da2 - > vram , 1024 * 1024 , 1 , f ) ;
fclose ( f ) ;
}
f = fopen ( " da2_gram.dmp " , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( da2 - > mmio . ram , 256 * 1024 , 1 , f ) ;
fclose ( f ) ;
}
f = fopen ( " da2_attrpal.dmp " , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( da2 - > attrc , 32 , 1 , f ) ;
fclose ( f ) ;
}
f = fopen ( " da2_dacrgb.dmp " , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( da2 - > vgapal , 3 * 256 , 1 , f ) ;
fclose ( f ) ;
}
f = fopen ( " da2_daregs.txt " , " w " ) ;
if ( f ! = NULL ) {
for ( int i = 0 ; i < 0x10 ; i + + )
fprintf ( f , " 3e1(ioctl) %02X: %4X \n " , i , da2 - > ioctl [ i ] ) ;
for ( int i = 0 ; i < 0x20 ; i + + )
fprintf ( f , " 3e3(fctl) %02X: %4X \n " , i , da2 - > fctl [ i ] ) ;
for ( int i = 0 ; i < 0x20 ; i + + )
fprintf ( f , " 3e5(crtc) %02X: %4X \n " , i , da2 - > crtc [ i ] ) ;
for ( int i = 0 ; i < 0x40 ; i + + )
fprintf ( f , " 3e8(attr) %02X: %4X \n " , i , da2 - > attrc [ i ] ) ;
for ( int i = 0 ; i < 0x10 ; i + + )
fprintf ( f , " 3eb(gcr) %02X: %4X \n " , i , da2 - > gdcreg [ i ] ) ;
for ( int i = 0 ; i < 0x10 ; i + + )
fprintf ( f , " 3ee(?) %02X: %4X \n " , i , da2 - > reg3ee [ i ] ) ;
fclose ( f ) ;
}
# endif
# ifdef ENABLE_DA2_DEBUGBLT
f = fopen ( " da2_bltdump.csv " , " w " ) ;
if ( f ! = NULL & & da2 - > bitblt . debug_reg_ip > 0 ) {
/* print header */
for ( int y = 0 ; y < DA2_DEBUG_BLTLOG_SIZE ; y + + ) {
if ( da2 - > bitblt . debug_reg [ ( da2 - > bitblt . debug_reg_ip - 1 ) * DA2_DEBUG_BLTLOG_SIZE + y ] ! = DA2_DEBUG_BLT_NEVERUSED )
fprintf ( f , " \" %02X \" \t " , y ) ;
}
fprintf ( f , " \n " ) ;
/* print data */
for ( int x = 0 ; x < da2 - > bitblt . debug_reg_ip ; x + + ) {
for ( int y = 0 ; y < DA2_DEBUG_BLTLOG_SIZE ; y + + ) {
if ( da2 - > bitblt . debug_reg [ x * DA2_DEBUG_BLTLOG_SIZE + y ] = = DA2_DEBUG_BLT_NEVERUSED )
;
else if ( da2 - > bitblt . debug_reg [ x * DA2_DEBUG_BLTLOG_SIZE + y ] = = DA2_DEBUG_BLT_USEDRESET )
fprintf ( f , " \" \" \t " ) ;
else
fprintf ( f , " \" %X \" \t " , da2 - > bitblt . debug_reg [ x * DA2_DEBUG_BLTLOG_SIZE + y ] ) ;
}
fprintf ( f , " \n " ) ;
}
fclose ( f ) ;
}
if ( da2 - > mmdbg_fp ! = NULL ) fclose ( da2 - > mmdbg_fp ) ;
if ( da2 - > mmrdbg_fp ! = NULL ) fclose ( da2 - > mmrdbg_fp ) ;
free ( da2 - > bitblt . debug_reg ) ;
# endif
free ( da2 - > cram ) ;
free ( da2 - > vram ) ;
free ( da2 - > changedvram ) ;
free ( da2 - > mmio . font ) ;
free ( da2 ) ;
}
void da2_speed_changed ( void * p )
{
da2_t * da2 = ( da2_t * ) p ;
da2 - > da2const = ( uint64_t ) ( ( cpuclock / DA2_PIXELCLOCK ) * ( float ) ( 1ull < < 32 ) ) ;
da2_recalctimings ( da2 ) ;
}
void da2_force_redraw ( void * p )
{
da2_t * da2 = ( da2_t * ) p ;
da2 - > fullchange = changeframecount ;
}
static const device_config_t da2_configuration [ ] = {
// clang-format off
{
. name = " charset " ,
. description = " Charset " ,
. type = CONFIG_SELECTION ,
. default_int = DA2_DCONFIG_CHARSET_JPAN ,
. selection = {
{
. description = " 932 (Japanese) " ,
. value = DA2_DCONFIG_CHARSET_JPAN
} ,
{
. description = " 938 (Traditional Chinese) " ,
. value = DA2_DCONFIG_CHARSET_HANT
} ,
{ . description = " " }
}
} ,
{
. name = " montype " ,
. description = " Monitor type " ,
. type = CONFIG_SELECTION ,
. default_int = DA2_DCONFIG_MONTYPE_COLOR ,
. selection = {
{
. description = " Color " ,
. value = DA2_DCONFIG_MONTYPE_COLOR
} ,
{
. description = " IBM 8515 " ,
. value = DA2_DCONFIG_MONTYPE_8515
} ,
{
. description = " Grayscale " ,
. value = DA2_DCONFIG_MONTYPE_MONO
} ,
{ . description = " " }
}
} ,
{ . name = " " , . description = " " , . type = CONFIG_END }
// clang-format on
} ;
const device_t ps55da2_device = {
. name = " IBM Display Adapter II (MCA) " ,
. internal_name = " ps55da2 " ,
. flags = DEVICE_MCA ,
. local = 0 ,
. init = da2_init ,
. close = da2_close ,
. reset = da2_reset ,
2025-02-15 12:08:50 +09:00
. available = da2_available ,
2025-02-15 08:27:17 +09:00
. speed_changed = da2_speed_changed ,
. force_redraw = da2_force_redraw ,
. config = da2_configuration
} ;
void
da2_device_add ( void )
{
if ( ! da2_standalone_enabled )
return ;
if ( machine_has_bus ( machine , MACHINE_BUS_MCA ) )
device_add ( & ps55da2_device ) ;
else
return ;
}