Jump to content
IGNORED

F18A programming, info, and resources


matthew180

Recommended Posts

Do all sprites share the same palette of 4 or 8 colors, or can each sprite use a different palette?

In the enhanced color modes (ECM), each sprite can reference any "palette".

 

There are 64 Palette Registers (PR) that are 12-bits each. Each PR is programmable and you can set any PR to any value (color) from >000 to >FFF (4095), i.e. there are 4-bits per red, green, and blue. The number of PRs is fixed, but the number of "palettes" at any time depends on the current ECM.

 

Having 64 PRs means you need 6-bits to address a PR for a pixel. In the original color mode, the sprite's color is an index into 1 of 4 main palettes. In the Enhanced Color Modes, the pattern data becomes part of the palette index. To complete the 6-bits to address a PR, there are 2-bits for sprites and 2-bits for tiles that come from the new "palette select" VDP Register (VR) VR24:

 

VR24:
 0  1  2  3  4  5  6  7 (Note, I use TI's bit numbering)
XX XX S0 S1 XX XX T0 T1
S0 and S1 are the "sprite palette select" and T0 and T1 are the "tile palette select". These two bits (two for sprites, two for tiles) are used to complete the 6-bit PR address when there are not enough pattern bits (original mode, ECM1 ECM2). Thus, for sprites, there are three places data comes from to select a pixel's color:

 

VR24: PS0&PS1 (sprite palette select bits)

Sprite attribute table: CS0 CS1 CS2 CS3 (color select)

Sprite pattern data: 0 to 3 bits

 

PS0&PS1 can be: 00, 01, 10, or 11, and are always the MSbits of the palette address, so they can select 1 of 4 groupings of PRs:

 

00xxxx PR0 to PR15
01xxxx PR16 to PR31
10xxxx PR32 to PR47
11xxxx PR48 to PR63
In the original color mode (ECM0), xxxx comes from the Sprite Attribute Table and will thus select 1-of-16 colors in the "palette" specified by the PS0&PS1 bits from VR24. This defaults to "00" and PR0 to PR15 are defaulted to the original 99/4A colors. In original mode, *pattern data* does not contribute to selecting a sprite pixel color, and simply indicates if the pixel is visible or not.

 

In ECM1 to ECM3, pattern data becomes part of building the PR address. The more pixel data, the less the PS0&PS1 are used, and the less of the sprite's color attribute (CS0 to CS3) is used:

 

PR Address bit: 0   1   2   3   4   5
--------------------------------------
original mode: ps0 ps1 cs0 cs1 cs2 cs3 (VR24 S0&S1 bits and SAT color index)
1-bit (ECM1) : ps0 cs0 cs1 cs2 cs3 px0 (VR24 S0 bit only, SAT color index, pattern bit)
2-bit (ECM2) : cs0 cs1 cs2 cs3 px1 px0 (SAT color index, two pattern bits)
3-bit (ECM3) : cs0 cs1 cs2 px2 px1 px0 (3 SAT color index bits, three pattern bits)
In ECM1 there are effectively 32 "palettes" with two colors each. VR24 PS0 and the SAT color (5-bits) make up the palette selection from 0 to 32, and the pattern bit selects one of the two colors in the "palette". Note that a sprite pattern value of zero "0", "00", or "000" is *always* transparent. So ECM1 for sprites is really only useful over original mode to enable the other enhanced sprite features.

 

In ECM2 there are effectively 16 "palettes" with four colors each. The sprite palette select bits from VR24 are now unused, and only the sprite's color from the SAT and the pattern data are used. So, in ECM2 the sprite's color in the SAT becomes a "palette select" from 0 to 15, and the two pattern bits select one of the four colors in the palette. Again, color "00" is transparent.

 

In ECM3 there are effectively 8 "palettes" with eight colors each. Only three bits from the sprite's color in the SAT are used to select the palette, and the three pattern bits select one of the eight colors in the palette. Color "000" is transparent.

 

So it is really a matter of how the 64 PRs are grouped and addressed based on the ECM. You can reprogram any of the PRs at any time, which will change the color of any pixel referencing that PR.

 

 

I'm not sure what you mean by "This allows you to start off with some existing sprite or tile patterns, and expand them to support more colors at a later time in your development."? It would be nice if you could keep the monochrome sprite pattern table unmodified and just add more planes when you switch to multi-color sprites, but that's not how it works, right? You will also need to replace the first plane/table.

The original Sprite Pattern Table is used for "px0" or the 0-bit in the ECMs, which means you can start with some existing sprite data in ECM2/ECM3 and the sprites will display in 1-color just as they were originally. Of course you have to set up your PRs accordingly, and make sure the additional sprite pattern tables are initialized to 0.

 

 

Could a future version of the firmware include an option only to have 1K or 512 bytes between the planes? This could save a lot of RAM if you only have a few sprite patterns. Having to reserve 6k for sprite patterns would be problematic in many cases.

Yes, that would probably be possible. However, as sometimes99er mentioned, if you only plan to use a few sprites then you can still use the memory in the pattern tables for other purposes. I do realized the memory would not be a nice neat linear block, but still usable.

Edited by matthew180
Link to comment
Share on other sites

On the first post of this thread I added two of the test programs I used when developing the F18A. The source and EA3 object file are included. The entry point is "MAIN" for both programs.

 

1. Scroll test. This is a test program for many of the VRs related to scrolling as well as a very basic palette test. It requires a joystick. Push the fire button to change the number of scroll "pages", but be sure to *hold* the fire button between presses to see the 30-row version of the current page mode, and of course move the joystick to scroll:

 

1: 1 page

* press and hold fire button
2: 1 page, 30-rows

* release fire button
3: 2 vertical pages:
   pg1
   ---
   pg3

* press and hold fire button
4: 2 vertical pages, 30-rows
   pg1
   ---
   pg3

* release fire button
5: 2 horizontal pages
   pg1 | pg2

* press and hold fire button
6: 2 horizontal pages, 30-rows
   pg1 | pg2

* release fire button
7: 4 pages:
   pg1 | pg2
   ----+----
   pg3 | pg4

* press and hold fire button
8: 4 pages, 30-rows
   pg1 | pg2
   ----+----
   pg3 | pg4
2. ECM3. Example of an 8-color sprite and custom palette. You should recognize the sprite. Move with the joystick, fire button to advance the sprite's frame (hold fire button while moving for travel effect). If I was not so lazy I would have flipped the sprite with the new FLIP-X parameter in the SAT (active in ECM1 to ECM3) when moving left.
Link to comment
Share on other sites

Matthew, I can't seem to find the information on the boot time requirements of the F18A... i.e. how much time I should hold the connected processor in reset before accessing the F18A?

Ideally about 200ms or so. Based on the Flash ROM I used and configuration speed settings the Xilinx datasheets indicate it should be done within 100ms. The FPGA does provide a *done* signal that could be used in a more integrated system, but the F18A has no provision to offer that output. Hmm, I suppose that could be added in a future version. The LED on the F18A comes on when it is done configuring, so if you are building your own computer you could hack into that output to release the system from reset.

 

But any delay over 200ms should be completely reliable. The ColecoVision has a *very short* reset and on an unmodified CV I found I typically had to hit the reset after a power on. Although changing the capacitor in the reset circuit made my own CV work 100% with the F18A.

Link to comment
Share on other sites

Ideally about 200ms or so. Based on the Flash ROM I used and configuration speed settings the Xilinx datasheets indicate it should be done within 100ms. The FPGA does provide a *done* signal that could be used in a more integrated system, but the F18A has no provision to offer that output. Hmm, I suppose that could be added in a future version. The LED on the F18A comes on when it is done configuring, so if you are building your own computer you could hack into that output to release the system from reset.

 

But any delay over 200ms should be completely reliable. The ColecoVision has a *very short* reset and on an unmodified CV I found I typically had to hit the reset after a power on. Although changing the capacitor in the reset circuit made my own CV work 100% with the F18A.

Thanks!
Link to comment
Share on other sites

In the enhanced color modes (ECM), each sprite can reference any "palette".

That's what I hoped to hear. Clever to use the original color attribute to select the palette. Good to have this documented.

 

The original Sprite Pattern Table is used for "px0" or the 0-bit in the ECMs, which means you can start with some existing sprite data in ECM2/ECM3 and the sprites will display in 1-color just as they were originally. Of course you have to set up your PRs accordingly, and make sure the additional sprite pattern tables are initialized to 0.

So it's more forwards than backwards compatibility: you can easily display your original patterns in ECM, but designing ECM sprites that fall back nicely to standard mode is more difficult.

 

Another easy approach to multi-colored sprites on the F18A (if you don't need a lot of sprites) is to use sprite linking: If an F18A is detected you add additional linked sprites that are extra color layers to the original sprites. Will linked sprites trigger the collision flag if they share pixels?

 

Yes, that would probably be possible. However, as sometimes99er mentioned, if you only plan to use a few sprites then you can still use the memory in the pattern tables for other purposes. I do realized the memory would not be a nice neat linear block, but still usable.

Sure, but in full bitmap mode you don't even have two contiguous 2K blocks to use.

Link to comment
Share on other sites

Good to have this documented.

Good to have someone making use of the information.

 

So it's more forwards than backwards compatibility: you can easily display your original patterns in ECM, but designing ECM sprites that fall back nicely to standard mode is more difficult.

Designing pattern/color data for the ECMs is a hassle, I realize that. A tool is definitely going to be a requirement for any serious ECM tile/sprite design. One of the versions of the Flash-based spite designer that sometimes99er wrote has initial support for ECM sprites, but that's the only tool so far.

 

Will linked sprites trigger the collision flag if they share pixels?

Yes, they will trigger a collision. Linking does not affect or suppress the collision detection, it only modifies the meaning of a sprite's x,y coordinates.

 

Sure, but in full bitmap mode you don't even have two contiguous 2K blocks to use.

True. But the idea of adding the features for tiles and sprites, plus the hardware scrolling was that bitmap mode would not be necessary for the effects it was typically used for, i.e. more color options, pixel scrolling, etc. You can scroll a tile screen without needing any additional VRAM, pick up 4 colors with an additional 8-bytes per tile or sprite, save pattern data by using the horizontal/vertical flip options for tiles/sprites, etc.

Link to comment
Share on other sites

Designing pattern/color data for the ECMs is a hassle, I realize that. A tool is definitely going to be a requirement for any serious ECM tile/sprite design. One of the versions of the Flash-based spite designer that sometimes99er wrote has initial support for ECM sprites, but that's the only tool so far.

No problem, I will write a small Java program (30-40 lines of code) that reads 16 color palette PNG files and separates the layers into assembler DATA statements.

 

So, how is it going with the soft firmware upgrade? (nag, nag)

Link to comment
Share on other sites

In ECMs there is a setting to specify if a "00" or "000" pixel value means the pixel is transparent, or if the pixel should use the 0-index in the palette.

Only for tiles, not for sprites, right?

 

Another question: How do you detect the F18A while avoiding detection on the current version of Classic99? Can you read the value of status reg 14, for instance?

 

What are the standard values of the palette registers, is it the standard TI palette duplicated 4 times?

Link to comment
Share on other sites

Matthew posted a register-based detection mechanism for the F18A that will fail on Classic99, since I only implemented the GPU. You could also try to manipulate many of the extended registers (or try to read a register back from the GPU)... or I could just get around to adding a disable switch already... ;)

Link to comment
Share on other sites

So, how is it going with the soft firmware upgrade? (nag, nag)

Slowly. Although I should be getting a little more time in the near future, so hopefully sooner than later.

 

 

Only for tiles, not for sprites, right?

Yes, the zero index ("0", "00", or "000") for sprites is always transparent. For tiles you can specify if the zero index is transparent or the color found at the zero index. I thought I was careful to always make the distinction, but I probably got it wrong somewhere.

 

For tiles in the ECMs, the color table goes from 32-bytes in size to 256-bytes. This gives one attribute-byte per tile, instead of groups of eight tiles. A tile's attribute byte provides the ability to specify that a tile has priority over sprites, pattern flip x, pattern flip y, zero index is transparent, and 4-bits of palette select:

 

   0       1       2        3      4   5   6   7
| PRI | FLIP X | FLIP Y | TRANS | PS0 PS1 PS2 PS3 |
.

Note that a color of >000 in a palette register is *always* black and never transparent. The only way to get a transparent pixel is with sprites, or enable transparency for a tile via its attribute byte. When transparency is enabled, the palette register value for the zero index is irrelevant.

 

What are the standard values of the palette registers, is it the standard TI palette duplicated 4 times?

When the F18A is powered up, it defaults the four palettes as follows:

 

#0 standard 9918A colors

#1 an EMC1 version of palette #0

#2 IBM CGA colors

#3 an ECM1 version of palette #2

 

Note that palette changes will survive a reset, i.e. plugging in a cartridge or software reset. They only assume these defaults at power-on.

 

-- Palette 0, original 9918A NTSC color approximations
x"000", --  0 Transparent
x"000", --  1 Black
x"2C3", --  2 Medium Green
x"5D6", --  3 Light Green
x"54F", --  4 Dark Blue
x"76F", --  5 Light Blue
x"D54", --  6 Dark Red
x"4EF", --  7 Cyan
x"F54", --  8 Medium Red
x"F76", --  9 Light Red
x"DC3", -- 10 Dark Yellow
x"ED6", -- 11 Light Yellow
x"2B2", -- 12 Dark Green
x"C5C", -- 13 Magenta
x"CCC", -- 14 Gray
x"FFF", -- 15 White

-- Palette 1, ECM1 (0 index is always 000) version of palette 0
x"000", --  0 Black
x"2C3", --  1 Medium Green
x"000", --  2 Black
x"54F", --  3 Dark Blue
x"000", --  4 Black
x"D54", --  5 Dark Red
x"000", --  6 Black
x"4EF", --  7 Cyan
x"000", --  8 Black
x"CCC", --  9 Gray
x"000", -- 10 Black
x"DC3", -- 11 Dark Yellow
x"000", -- 12 Black
x"C5C", -- 13 Magenta
x"000", -- 14 Black
x"FFF", -- 15 White

-- Palette 2, CGA colors
x"000", --  0 >000000 (  0   0   0) black
x"00A", --  1 >0000AA (  0   0 170) blue
x"0A0", --  2 >00AA00 (  0 170   0) green
x"0AA", --  3 >00AAAA (  0 170 170) cyan
x"A00", --  4 >AA0000 (170   0   0) red
x"A0A", --  5 >AA00AA (170   0 170) magenta
x"A50", --  6 >AA5500 (170  85   0) brown
x"AAA", --  7 >AAAAAA (170 170 170) light gray
x"555", --  8 >555555 ( 85  85  85) gray
x"55F", --  9 >5555FF ( 85  85 255) light blue
x"5F5", -- 10 >55FF55 ( 85 255  85) light green
x"5FF", -- 11 >55FFFF ( 85 255 255) light cyan
x"F55", -- 12 >FF5555 (255  85  85) light red
x"F5F", -- 13 >FF55FF (255  85 255) light magenta
x"FF5", -- 14 >FFFF55 (255 255  85) yellow
x"FFF", -- 15 >FFFFFF (255 255 255) white

-- Palette 3, ECM1 (0 index is always 000) version of palette 2
x"000", --  0 >000000 (  0   0   0) black
x"555", --  1 >555555 ( 85  85  85) gray
x"000", --  2 >000000 (  0   0   0) black
x"00A", --  3 >0000AA (  0   0 170) blue
x"000", --  4 >000000 (  0   0   0) black
x"0A0", --  5 >00AA00 (  0 170   0) green
x"000", --  6 >000000 (  0   0   0) black
x"0AA", --  7 >00AAAA (  0 170 170) cyan
x"000", --  8 >000000 (  0   0   0) black
x"A00", --  9 >AA0000 (170   0   0) red
x"000", -- 10 >000000 (  0   0   0) black
x"A0A", -- 11 >AA00AA (170   0 170) magenta
x"000", -- 12 >000000 (  0   0   0) black
x"A50", -- 13 >AA5500 (170  85   0) brown
x"000", -- 14 >000000 (  0   0   0) black
x"FFF"  -- 15 >FFFFFF (255 255 255) white
.

Another question: How do you detect the F18A while avoiding detection on the current version of Classic99? Can you read the value of status reg 14, for instance?

Matthew posted a register-based detection mechanism for the F18A that will fail on Classic99, since I only implemented the GPU.

There is a rather involved way to detect the F18A that I designed to not conflict with the 9938/58, and still let you detect the F18A vs 9918A or 9938/58. However it is a pain the ass and someone else (I can't remember who) suggested to just use the GPU by putting a very simple GPU program in VRAM that sets a byte, trigger the GPU, then check the byte in VRAM. If the F18A is present then the simple GPU code would set (or clear) the byte in VRAM at a specific location. Much easier (and shorter) than using the status register method.

 

Here is an example I wrote for doing it the *easy* way:

 

       DEF MAIN

* VDP Memory Map
*
VDPRD  EQU  >8800             * VDP read data
VDPSTA EQU  >8802             * VDP status
VDPWD  EQU  >8C00             * VDP write data
VDPWA  EQU  >8C02             * VDP set read/write address

* Workspace
*
WRKSP  EQU  >8300             * Workspace
R0LB   EQU  WRKSP+1           * R0 low byte reqd for VDP routines

GPU
       DATA >04E0             * 3F00 04E0        CLR  @>3F00
       DATA >3F00             * 3F02 3F00
       DATA >0340             * 3F04 0340        IDLE
GPUEND

MAIN
       LIMI 0
       LWPI WRKSP

*      F18A Unlock
       LI   R0,>391C          * VR1/57, value 00011100
       BL   @VWTR             * Write once
       BL   @VWTR             * Write twice, unlock
       LI   R0,>01E0          * VR1, value 11100000, a useable setting
       BL   @VWTR             * Write reg

*      Copy GPU code to VRAM
       LI   R0,>3F00
       LI   R1,GPU
       LI   R2,GPUEND-GPU
       BL   @VMBW

*      Set the GPU program counter (PC), which will trigger the GPU
       LI   R0,>363F          * VR36 MSB of PC = >3F
       BL   @VWTR
       LI   R0,>3700          * VR37 LSB of PC = >00
       BL   @VWTR

*      Compare the result in >3F00
       LI   R0,>3F00
       BL   @VRAD
       MOVB @VDPRD,R0
       JEQ  PASS
*
FAIL
*
PASS
.

Here is a complete F18A detection the *hard way*. This will probably give a "No F18A" on Classic99 since I don't think Tursi added the extra status registers yet. Since this method involves reading the status byte, sprites must be disabled and it has to wait for VSYNC so none of those status bits (collision or interrupt) interfere with the detection on a non-F18A system. This was tested on a real console with and without and F18A, and on Classic99.

 

 

 

**
* Matthew Hagerty
* http://codehackcreate.com
* May 2012
*
* Basic setup for using the F18A in the 99/4A console.
* Performs the unlock sequence and detects if the F18A
* is present in the system.
*
* Run from EA3.
* Tested on real 99/4A with F18A
* Tested on real 99/4A with 9918A
* Tested on Classic99

       DEF  MAIN

* VDP Memory Map
*
VDPRD  EQU  >8800             * VDP read data
VDPSTA EQU  >8802             * VDP status
VDPWD  EQU  >8C00             * VDP write data
VDPWA  EQU  >8C02             * VDP set read/write address

* Workspace
*
WRKSP  EQU  >8300             * Workspace
R0LB   EQU  WRKSP+1           * R0 low byte reqd for VDP routines

* Constants
*
VSTAT  DATA >8000             * VDP vsync status
NUM_00 BYTE 0                 * Number 0
NUM_01 BYTE 1                 * Number 1

MSG01  TEXT 'F18A V0.0 DETECTED'
MSG01E
MSG02  TEXT 'F18A NOT FOUND'
MSG02E

* Variables
*
F18AFG BYTE 0                 * 1 if the F18A is detected

       EVEN

**
* Main program entry point
*
MAIN
       LIMI 0                 * Interrupts need to be off for these checks
       LWPI WRKSP

*      Clear the screen
       CLR  R0                * Write to VRAM >0000 (name table location)
       LI   R1,>2000          * Space to screen
       LI   R2,768
       BL   @VSMW

*      Perform the Enhance Register Mode (ERM) unlock sequence
*      for the F18A.
       LI   R0,>391C          * VR1/57, value 00011100
       BL   @VWTR             * Write once
       BL   @VWTR             * Write twice, unlock
       LI   R0,>01E0          * VR1, value 11100000, a real sane setting
       BL   @VWTR             * Write reg

*      Set up the sprite attribute table and set the sprite 0 Y value
*      to >D0 to disable sprites.  This keeps sprite processing from
*      conflicting with SR0 (status register 0) bits F, 5S, and C, which
*      are in the same position as the ID bits on SR1 on the F18A.
       LI   R0,>0506          * satba @ >0300, default but just make sure
       BL   @VWTR             * Write reg
       LI   R0,>0300          * Y value of sprite 0
       LI   R1,>D000          * >D0 to Y value
       BL   @VSBW             * Write byte to VDP

*      Wait for vsync
VWAIT
       CLR  R1
       MOVB @VDPSTA,R1        * Reading clears the VDP sync indicator
       COC  @VSTAT,R1         * Check for interrupt flag
       JNE  VWAIT             * No vsync, so wait
*      The F, 5S, and C flags are now clear and won't interfere with the ID bits

       LI   R2,MSG02E-MSG02   * Length of message
       LI   R3,MSG02          * Set up the default message to no F18A

       LI   R0,>0F01          * VR15, change to read SR1 on unlocked F18A, write to VR7 on 9918A/locked F18A
       BL   @VWTR             * Write reg
       MOVB @VDPSTA,R1        * Read SR1 on F18A, SR0 on 9918A
       ANDI R1,>E000          * Mask the F18A status bits, ANDI sets EQ flag if zero (not an F18A)
       JEQ  NOF18A

*      F18A ID found
       AB   @NUM_01,@F18AFG   * Set the "have F18A" flag
       LI   R0,>0F0E          * Set VR15 to read SR14 which is the F18A version info
       BL   @VWTR             * Write reg
       MOVB @VDPSTA,R1        * Read SR14 on F18A, SR0 on 9918A
*      MSB of R1 now contains major/minor version: MJ0 MJ1 MJ2 MJ3 | MN0 MN1 MN2 MN3 = >1300 (1.3)
       LI   R0,>0F00          * Restore VR15 to >00 = read SR0 when reading VDP status
       BL   @VWTR             * Write reg

*      Set the version in the message
       LI   R3,MSG01
       MOV  R1,R2             * Copy to R2, will become isolated minor part
       SRL  R1,4              * Move major part to bottom bits of MSB
       ANDI R1,>0F00          * Isolate the major part
       ANDI R2,>0F00          * Isolate the minor part
       AB   R1,@MSG01+6       * Major version byte in message
       AB   R2,@MSG01+8       * Minor version byte in message
       LI   R2,MSG01E-MSG01   * Message length

NOF18A
       LI   R0,>07C1          * Restore VR7 if necessary (dark green on black)
       BL   @VWTR             * Write reg

*      Write a message to the screen based on the detection of the F18A
       LI   R0,392            * About the middle of the screen
       MOV  R3,R1             * R3 is set to the message to write, R0 is needed for VMBW
       BL   @VMBW             * Write message to screen (R2 length is already set)

DONE
       LIMI 2
       JMP  DONE


*********************************************************************
*
* VDP Single Byte Write
*
* R0   Write address in VDP RAM
* R1   MSB of R1 sent to VDP RAM
*
* R0 is modified, but can be restored with: ANDI R0,>3FFF
*
VSBW   MOVB @R0LB,@VDPWA      * Send low byte of VDP RAM write address
       ORI  R0,>4000          * Set read/write bits 14 and 15 to write (01)
       MOVB R0,@VDPWA         * Send high byte of VDP RAM write address
       MOVB R1,@VDPWD         * Write byte to VDP RAM
       B    *R11
*// VSBW


*********************************************************************
*
* VDP Single Byte Multiple Write
*
* R0   Starting write address in VDP RAM
* R1   MSB of R1 sent to VDP RAM
* R2   Number of times to write the MSB byte of R1 to VDP RAM
*
* R0 is modified, but can be restored with: ANDI R0,>3FFF
*
VSMW   MOVB @R0LB,@VDPWA      * Send low byte of VDP RAM write address
       ORI  R0,>4000          * Set read/write bits 14 and 15 to write (01)
       MOVB R0,@VDPWA         * Send high byte of VDP RAM write address
VSMWLP MOVB R1,@VDPWD         * Write byte to VDP RAM
       DEC  R2                * Byte counter
       JNE  VSMWLP            * Check if done
       B    *R11
*// VSMW


*********************************************************************
*
* VDP Multiple Byte Write
*
* R0   Starting write address in VDP RAM
* R1   Starting read address in CPU RAM
* R2   Number of bytes to send to the VDP RAM
*
* R0 is modified, but can be restored with: ANDI R0,>3FFF
*
VMBW   MOVB @R0LB,@VDPWA      * Send low byte of VDP RAM write address
       ORI  R0,>4000          * Set read/write bits 14 and 15 to write (01)
       MOVB R0,@VDPWA         * Send high byte of VDP RAM write address
VMBWLP MOVB *R1+,@VDPWD       * Write byte to VDP RAM
       DEC  R2                * Byte counter
       JNE  VMBWLP            * Check if done
       B    *R11
*// VMBW


*********************************************************************
*
* VDP Single Byte Read
*
* R0   Read address in VDP RAM
* R1   MSB of R1 set to byte from VDP RAM
*
VSBR   MOVB @R0LB,@VDPWA      * Send low byte of VDP RAM write address
       MOVB R0,@VDPWA         * Send high byte of VDP RAM write address
       MOVB @VDPRD,R1         * Read byte from VDP RAM
       B    *R11
*// VSBR


*********************************************************************
*
* VDP Multiple Byte Read
*
* R0   Starting read address in VDP RAM
* R1   Starting write address in CPU RAM
* R2   Number of bytes to read from VDP RAM
*
VMBR   MOVB @R0LB,@VDPWA      * Send low byte of VDP RAM write address
       MOVB R0,@VDPWA         * Send high byte of VDP RAM write address
VMBRLP MOVB @VDPRD,*R1+       * Read byte from VDP RAM
       DEC  R2                * Byte counter
       JNE  VMBRLP            * Check if finished
       B    *R11
*// VMBR


*********************************************************************
*
* VDP Write To Register
*
* R0 MSB    VDP register to write to
* R0 LSB    Value to write
*
VWTR   MOVB @R0LB,@VDPWA      * Send low byte (value) to write to VDP register
       ORI  R0,>8000          * Set up a VDP register write operation (10)
       MOVB R0,@VDPWA         * Send high byte (address) of VDP register
       B    *R11
*// VWTR

       END

 

Edited by matthew180
  • Like 1
Link to comment
Share on other sites

Thanks, I hope Tursi will make a GPU toggle soon.

 

Another question. Below you wrote that for multicolor sprites the first pattern plane contains the most significant bit of the color index:

 

To get a pixel's color index, you combine the bits vertically (referring to the example able) from each pattern byte in each plane, for a given pixel location in the byte. So, the second pixel is "01", or index 1. The first byte in the pattern represents the MSbit in the final index value. A 3-bpp sprite using all eight colors in a row would be like this across the three bit-planes:

 

000 - 0 (color index 0 or transparent, depending)
001 - 1
010 - 2
011 - 3
100 - 4
101 - 5
110 - 6
111 - 7

00001111 pattern-plane 1, 2K total
00110011 pattern-plane 2, 4K total, 2048 bytes offset from the SPGT
01010101 pattern-plane 3, 6K total, 4096 bytes offset from the SPGT
--------
01234567 color index values.

 

Are you sure this is correct, because I'm experiencing the opposite? I.e. with 4 color sprites I have to put the most significant bit in pattern-plane 2 and the least significant bit in pattern-plane 1. Otherwise the two middle colors of the palette (index 1 and 2) are flipped. I may bee doing something else wrong, of course, like setting the palettes wrong.

 

Thanks,

Rasmus.

Link to comment
Share on other sites

Nope, you are not doing anything wrong, I wrote it up backwards. The first bit-plane is the LSb of the color index. I'll correct that post you quoted. Any time you see something wrong like that please let me know so I can fix it.

 

Edit: Although in post #26 of this thread I did document it correctly.

Edited by matthew180
Link to comment
Share on other sites

I thought a easy way would be to just load values into the VDP registers and check the values against the amount of memory of the VDP.

 

The additional check for a 9958 vs 9938 was to then check for the Mouse option to see if that VDP Register value came back or not.

 

That way a normal 9918 would return only 16K and a F18A would return more memory and the 9938 and 9958 would both return more VDP memory.

 

The great thing about this was it can be done from a very very small Assembly program or even GPL.

Link to comment
Share on other sites

How does the 9918A "return" the amount of VRAM? For that matter, how does the F18A "return" an amount of VRAM? An example of the very small assembly program you mentioned would be helpful.

 

The problem with just "loading up" registers is that on a 9918A any VDP Register (VR) over VR7 will start to repeat VR0 - VR7, and you will end up trashing the video mode, interrupt bit, VDP table settings, etc. It also does not help you determine what VDP is in the system.

Link to comment
Share on other sites

How does the 9918A "return" the amount of VRAM? For that matter, how does the F18A "return" an amount of VRAM? An example of the very small assembly program you mentioned would be helpful.

 

The problem with just "loading up" registers is that on a 9918A any VDP Register (VR) over VR7 will start to repeat VR0 - VR7, and you will end up trashing the video mode, interrupt bit, VDP table settings, etc. It also does not help you determine what VDP is in the system.

 

 

I was considering setting a VDP Register at the upper limit of the TI memory like say set the Screen Image to >10 then the very last byte of that table is >42FF but 16K ends at >3FFF

So if you write >10 in VDP Register #2 i.e. >400 times >10 equals >4000 so then write a byte to >4000 and read that byte at >4000 you would find out if it wraps or not.

 

If the byte is at >0000 and not >4000 then you have a 9918 as in Graphics mode 1 but if does not wrap back but goes to >4000 then some other expanded memory of VDP exists.

 

The 9938 and 9958 both had 64K of VDP per page so >FFFF of VDP memory per page. The normal TI tops out at >3FFF this seemed like a good easy solution to test for.

 

I should add that this method DOES NOT CRASH the TI. As far as I can tell the 9918A just ignores the 1 in >10 as it is to large and only accepts a value up to >0F so >1F is the same result.

Edited by RXB
Link to comment
Share on other sites

Yes, sprites are available as well as the bitmap layer. Also, the text modes (40 and 80 column) get some extra color support in the enhanced color modes (ECM).

 

These images show the 40 and 80 column modes ECM1 enabled. You can see all 32-sprites displayed on a single line (the colored boxes), the bitmap layer is enabled (the orange an yellow rectangle of random pixels), color support, tile flip-x and flip-y, and some priority over sprites for certain tiles.

 

Edit: I should note that to support sprites in the text modes you have to be in ECM1, ECM2, or ECM3. Text modes in the original color mode (i.e. 9918A compatible) do not support sprites. I had to do that to prevent sprites from possibly showing up in existing software since disabling sprites was not necessary in text modes, some software probably did not even bother to set the SAT and load >D0 to the first Y location.

post-24952-0-09638600-1380074634_thumb.jpg

post-24952-0-99236300-1380074634_thumb.jpg

Edited by matthew180
Link to comment
Share on other sites

Why did no one respond to my way to check for what Size of VDP RAM?

 

A 9918 will just wrap any value and ignore the first byte as it only has 16K, while any other chips have more VDP RAM so will give you a write and read that shows the size.

 

Example: >0F (>3C00) or >1F (>7C00) or >2F (>BC00) are the same value for Screen Image table in a 9918 and on the other hand will be valid address for a 9938 or 9958.

 

And my method will not crash a normal TI at all. It requires you only change one (1) VDP Register to find the type of VDP chip and size.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...