blog:pc98_devcode

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
blog:pc98_devcode [2020/08/22 08:56] – [Packed-Pixel or Chunky Video Modes] johnblog:pc98_devcode [2020/08/22 09:48] (current) – [PC-9821 PEGC 256 Colour Graphics Hardware] john
Line 3: Line 3:
 So you've got your NP21Kai PC-98 emulator up and running, or you've resurrected an ancient NEC PC-9801 or PC-9821 and you've decided you want to do some C programming for it. So you've got your NP21Kai PC-98 emulator up and running, or you've resurrected an ancient NEC PC-9801 or PC-9821 and you've decided you want to do some C programming for it.
  
-Where do you start? Well, first, get a working development environment up and running. [[blog:pc98_devtools|You can get one here]]. +Where do you start? Well, first, get a working development environment up and running. [[blog:pc98_devtools|You can get one here on the development tools page]]. 
  
 Next you will want to figure out how to do some interesting things with the hardware, as otherwise it's just a normal command line DOS machine.... Next you will want to figure out how to do some interesting things with the hardware, as otherwise it's just a normal command line DOS machine....
 +
 +===== Pre-Requisites =====
 +
 +After [[blog:pc98_devtools#makefiles_Compiling|compiling]] your code, your application will need the following to run:
 +
 +     * A VCPI memory mapper running (EMM386, VEMM486 or similar)
 +     * A DPMI server running
 +     * A copy of GO32-V2.exe in the same directory as your application
 +
 +The VCPI memory mapper should be started at boot, but the DPMI server only needs to be run at the time your application starts.
 +
 +A copy of DPMI.EXE and GO32-V2.EXE are including on the development tools page.
 ===== Non-hardware Specific Examples ===== ===== Non-hardware Specific Examples =====
  
Line 37: Line 49:
 ===== PC-9821 PEGC 256 Colour Graphics Hardware ===== ===== PC-9821 PEGC 256 Colour Graphics Hardware =====
  
 +There are several generations of custom graphics hardware on the PC-98:
 +
 +     * PC-9801, GDC: 640x400, 8 colour, 96KB VRAM (later 192KB)
 +     * PC-9801VF, GC: 640x400, 16 colour, 96KB VRAM (later 192KB)
 +     * PC-9801VX, EGC: 640x400, 16 colour, 256KB VRAM, added raster operation functions, bitblt and bit shift functions
 +     * PC-9821AP, PEGC: 640x400, 256 colour, 512KB VRAM, added packed-pixel and planar addressing modes
 +
 +The systems are //generally// backwards compatible, so a PC-9821 //should// be able to run software designed for early PC-9801 machines... cpu speed dependent, of course.
 +
 +My focus is on the later PEGC, 256 colour systems, since (a) this is the hardware I actually own, and (b), its most similar to DOS VGA or modern framebuffer hardware.
 ==== Packed-Pixel or Chunky Video Modes ==== ==== Packed-Pixel or Chunky Video Modes ====
  
Line 229: Line 251:
 </code> </code>
  
-//Note: You may want to create your DPMI memory info structure and VRAM selector object as globals, since anything writing to the framebuffer (see next example, below) will need to access them.//+It is this section of code which I used to test the functionality of the various DPMI services on PC-98 DOS. The only one which would correctly return all of the various dpmi calls was the **MS-DOS 6.22 DPMI.EXE**. There may be other third party DPMI services, but since this one comes with DOS itself, it's probably the easiest (and most reliable) one to obtain. 
 + 
 +//Note: You may want to create your DPMI memory info structure (__vram_dpmi__) and VRAM selector object (__vram_dpmi_selector__) as globals, since anything writing to the framebuffer (see next example, below) will need to access them.//
  
 ---- ----
Line 241: Line 265:
    * _farpokeb(), _farpokew(), _farpokel()  - To set individual bytes (8), short (16) or long (32) words    * _farpokeb(), _farpokew(), _farpokel()  - To set individual bytes (8), short (16) or long (32) words
    * _farpeekb(), _farpeekw(), _farpeekl()  - To get individual bytes, short or long words    * _farpeekb(), _farpeekw(), _farpeekl()  - To get individual bytes, short or long words
-   * movedata() - To transfer contiguous blocks of memory+   [[http://www.delorie.com/djgpp/doc/libc/libc_583.html|movedata]] - To transfer contiguous blocks of memory 
 + 
 +You //can//, therefore write directly to the framebuffer if you wish, but it's probably easier to create a local buffer which you write into first, compositing all of your display elements, and then transfer the entire buffer in one operation to the framebuffer hardware. 
 + 
 +<code "C"> 
 +     #include <dos.h> 
 +     #include <go32.h> 
 +     #include <dpmi.h> 
 +      
 +     // Define the size of the screen 
 +     #define GFX_ROWS 400 // Number of pixels in a row 
 +     #define GFX_COLS 640 // Number of pixels in a column 
 +      
 +     // Create a local vram buffer 
 +     unsigned char vram_buffer[(GFX_ROWS * GFX_COLS)]; 
 +      
 +     // Do all your operations on the vram_buffer 
 +     // ... 
 +     // ... 
 +      
 +     // Now transfer the local buffer to the actual graphics hardware 
 +     // _my_ds() - is a DJGPP function which selects the correct DOS memory 
 +     // selector of any variable in your running code. 
 +     // vram_buffer - is the structure in local memory we have written our graphics into 
 +     // vram_dpmi_selector - is the VRAM framebuffer DPMI selector we created earlier. 
 +     // 0 - is the offset into the far memory we want to copy to, in this case we are copying the entire region, so it is 0 
 +     // GFX_ROWS * GFX_COLS - is the number of bytes to copy from the source... this should be 256KB in this case 
 +     movedata(_my_ds(), vram_buffer, vram_dpmi_selector, 0, (GFX_ROWS * GFX_COLS)); 
 +</code> 
 + 
 +The use of //movedata()// is slightly restrictive in that the size of data transferred must be a multiple of 32bit long words, so it's better used for transferring larger blocks of memory; altering single (or a few) bytes is better done with the //_farpoke()// calls. 
 + 
 +//Note: In 256 colour 640x400 mode, you actually have two pages of VRAM to write to, so you could in fact do double-buffered output by writing first to the first 0-256KBytes of VRAM, displaying it, and then writing to the 256-512KBytes of VRAM. You can control which portion of VRAM is displayed at any given time by writing __0x00__ or __0x01__ to port __0xA4__. 
 +If you have chosen a 640x480 resolution, then you can only have a single page of VRAM, as a single screen is >256KBytes in size.// 
 ==== Planar Video Modes ==== ==== Planar Video Modes ====
  
 +Planar access in 256 colour mode is only supported on a small subset of PC-9821 machines according to http://radioc.web.fc2.com/column/pc98bas/pc98disphw_en.htm.
 +
 +    * PC-9821Ap, Ap2 (Ap3 is specifically //not// supported)
 +    * PC-9821As, As2
 +    * PC-9821Ae 
 +    * PC-9821Af
 +    * PC-9821An
 +    * PC-9821Ce, Ce2
 +    * PC-9821Cs2
 +    * PC-9821Ne
 +
 +For this reason (it limits the use of any of your code to the small number of machines above), I am //not// intending to cover this specific mode. 
 +
 +There is a vanishingly small amount of existing software which uses this mode - the most well known being the [[https://github.com/joncampbell123/dosbox-x/issues/1061|PC-98 Windows 3.1 256 colour PEGC driver]].
 ===== PC-9821 EGC 16 Colour Graphics Hardware ===== ===== PC-9821 EGC 16 Colour Graphics Hardware =====
  
 +TO DO
 ==== Planar Video Modes ==== ==== Planar Video Modes ====
 +
 +TO DO
  • blog/pc98_devcode.1598086569.txt.gz
  • Last modified: 2020/08/22 08:56
  • by john