Jump to content
IGNORED

F18A programming, info, and resources


matthew180

Recommended Posts

On 7/28/2023 at 1:04 AM, matthew180 said:

The F18A follows the standard VGA pin-out:

 

1 R

2 G

3 B

5, 6, 7, 8, 10 GND

13 HSYNC

14 VSYNC

 

All others are no-connect.

 

Physical header is the same as the attached diagram.  Look at the top of the PCB:

 

 1 2

 3 4

 5 6

 7 8

 9 10

11 12

13 14

15 16

 

 

f18a_vga_pinout.png

@matthew180 can you tell me the pitch needed on the 16 pin IDC cable to connect to the F18a. I don't want to take it apart until I've got all the cables I need.

Link to comment
Share on other sites

  • 3 months later...

I am reading through the documentation, but a lot of stuff seems conflicting or out-of-date. Am I limited to only 256 tiles when using any of the ECM modes? No more 3 sets of 256 tiles on screen? 

Link to comment
Share on other sites

1 hour ago, opcode said:

I am reading through the documentation, but a lot of stuff seems conflicting or out-of-date. Am I limited to only 256 tiles when using any of the ECM modes? No more 3 sets of 256 tiles on screen? 

Correct. I think the F18A will ignore the ECM settings if you use mode 2. But in mode 1 you could probably use the GPU and the hsync trigger to switch between 3 different patterns tables while the screen is drawn. Alternatively you could fill the screen with a real bitmap (either 256x192 in 4 colors or 128x192 in 16 colors). 

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

2 hours ago, Asmusr said:

Correct. I think the F18A will ignore the ECM settings if you use mode 2. But in mode 1 you could probably use the GPU and the hsync trigger to switch between 3 different patterns tables while the screen is drawn. Alternatively you could fill the screen with a real bitmap (either 256x192 in 4 colors or 128x192 in 16 colors). 

Thank you. Sounds like a lot of VRAM is left unused in some modes, and I wonder why some extra name bits weren't added to the new attributes, but I guess it is what it is.

Link to comment
Share on other sites

59 minutes ago, opcode said:

Thank you. Sounds like a lot of VRAM is left unused in some modes, and I wonder why some extra name bits weren't added to the new attributes, but I guess it is what it is.

In ECM3 the tile pattern table takes 6k, the sprite pattern table another 6K, the name table 768 bytes and the tile attributes table 256 bytes. That leaves only 3K for other things like disk buffers. If you want to use scrolling the name table can take 2k or 4k, leaving no space for anything else. I agree it would be great to be able to use more tiles, but in ECM3, 768 tiles would take 18k. In ECM2 it would only take 12k, but how would you store a 10 bit name table?

  • Like 1
Link to comment
Share on other sites

On 1/11/2024 at 9:41 AM, opcode said:

I am reading through the documentation, but a lot of stuff seems conflicting or out-of-date. Am I limited to only 256 tiles when using any of the ECM modes? No more 3 sets of 256 tiles on screen? 

 

Yeah, the documentation is lacking and the forum covers the full life-span of the F18A, and the features changed over time (and will change again).  The latest info is always going to be the most accurate.  One day I hope to write some decent documentation for the F18A.  Until then, asking questions here is the best way to get details (or read the VHDL).

 

As Asmusr mentioned, the ECM modes only use GM1 tile addressing.  As Asmusr also points out, it has more to do with available memory (ECM3-GM2 would not be possible), however it might be feasible in the hybrid-mode.  I'll take a note to look at this in more detail while I'm rewriting for the MK1 and MK2 updates.

 

22 hours ago, opcode said:

Thank you. Sounds like a lot of VRAM is left unused in some modes, and I wonder why some extra name bits weren't added to the new attributes, but I guess it is what it is.

 

VRAM is certainly underutilized in some modes, and painfully not enough in others.  Also, the flexibility of the table-based nature of the 9918A can make it difficult to use sometimes, and over complicated the design IMO (flexibility always comes at a cost).

 

There is no mode on the 9918A that uses 9 or 10 bit names, so there was no way to add those bits that was compatible with any existing mode or way of doing things on the 9918A.  When you only need one or two more bits (i.e. 9 or 10-bit names), it also becomes a PITA to manage the tile name since it is split across multiple bytes (and the extra bits get packed in with other unrelated bits somewhere).  Bit-planes is the usual solution to this in other graphic hardware of the era.

 

I chose the extra attribute-byte features based what I found in some other VDPs like on the NES (flip x,y IIRC), as well as features I thought might be useful.  Certainly extra name-bits were considered, but it was a one-sided conversation (me talking to myself), so I had to decide.

 

If you need more unique tiles, you can use the 2nd tile-layer, which has its own name-table register, so that will give you 512 unique tiles, plus each tile layer can have its own ECM, so one of them could use more pattern data when more color is needed, etc..

 

There is usually a way to achieve the desired goal, as long as the expectations are within reason for what the VDP is.  There is a tendency for people to only focus on what the VDP is not capable of, without considering the balance with the rest of the machine and the limitations as they were at the time the 9918A was created.  Finding creative ways to work with the features the VDP does provide, will usually yield much better and enjoyable results.

 

The main features the F18A gives you are more colors for tiles and sprites, an extra tile-layer, some hardware scrolling support, all sprites visible on a scan line, independent sprite size, changeable palette, and a GPU to help with moving data and other similar tasks.

  • Like 3
Link to comment
Share on other sites

IMO the only thing the F18A really, really needs is a bit more RAM. You can use the GPU for a lot of cool stuff, but there's very little room to store the data for the stuff, which absolutely needs to be in VDP RAM to take advantage of the GPU. Just 16K extra available to the GPU would make a lot of my ideas possible.

  • Like 5
Link to comment
Share on other sites

  • 3 weeks later...

I read earlier in the thread that the F18a detection routine doesn't work with Classic99

 

Is this still the case please? (I get a bright green screen and a lock up when running the code in page 1 of this thread from EA option 3)

 

If it is the case, is there any emulator that emulates F18a and supports detection please?

 

Many thanks

Link to comment
Share on other sites

There's a lot going on in page 1 - what code doesn't work?

 

I don't know if I implemented the ID registers that Matt's original code uses, but most detection code now just tries to run the GPU to change a byte of RAM, and that most certainly works fine in Classic99.

 

JS99er.net has a full F18A implementation as far as I know

 

Link to comment
Share on other sites

This is the code I use to detect the F18A. There's a lot of code here, but it's complete with VDP utilities and the like. All it does is:
 

1: Unlock the F18A

2: Copy a short piece of GPU code to VDP RAM - this code just sets a fixed value to a fixed VDP address

3: Make sure that VDP address contains >0000 (so previous runs don't affect it)

4: Start the GPU

5: Read the VDP data

6: Test if it contains the fixed data or not

 

* Check if F18A is present, return unlocked if so, else
* just restart.
TESTF18
* We just check if the GPU is present by having it run a short program
* F18A blind unlock code
	MOV R11,@SAVE
	
	LI R0,>B280				* VR2/50, value 10000000
	BL @VDPWA				* reset and lock F18A, or corrupt R2
	
	LI R0,>B91C             * VR1/57, value 00011100
	BL @VDPWA               * write once (corrupts VDPR1)
	BL @VDPWA               * write again (unlocks enhanced mode)

* If we are not on the F18, then R1 is screwed up now, that's okay
	LI R0,>1C00
	LI R1,GPUTEST
	LI R2,10
	BL @VMBW				* copy program
	
	LI R0,>1C10				* test address
	CLR R1
	BL @V2BW				* clear it
	
* Start the GPU program, pause, then check the result
	LI R0,>B61C				* MSB
	BL @VDPWA
	LI R0,>B700				* LSB and start
	BL @VDPWA
	NOP						* give it a moment - it's WAY faster than we are
	LI R0,>1C10
	BL @V2BR				* read the data
	CI R1,>1234
	JEQ F18YES
** Do your F18A does not exist code here
    BLWP @>0000

F18YES
	MOV @SAVE,R11
	B *R11

GPUTEST
	DATA >0200,>1234		LI R0,>1234
	DATA >C800,>1C10		MOV R0,@>1C10
	DATA >0340				IDLE

SAVE  BSS 2

* Write address or register
VDPWA
	SWPB R0
	MOVB R0,@>8C02
	SWPB R0
	MOVB R0,@>8C02
	B *R11  

* Write R2 bytes from CPU R1 to VDP R0
* Destroys R0,R1,R2
VMBW
	ORI R0,>4000
	SWPB R0
	MOVB R0,@>8C02
	SWPB R0
	MOVB R0,@>8C02
VMBWLP
	MOVB *R1+,@>8C00
	DEC R2
	JNE VMBWLP
	B *R11

* Write two bytes to R0 from R1
* Destroys R0 (actually just oRs it)
V2BW
	ORI R0,>4000
	SWPB R0
	MOVB R0,@>8C02
	SWPB R0
	MOVB R0,@>8C02
	MOVB R1,@>8C00
	SWPB R1
	MOVB R1,@>8C00
	B *R11

* Reads two bytes from R0 to R1
V2BR
	SWPB R0
	MOVB R0,@>8C02
	SWPB R0
	MOVB R0,@>8C02
	MOVB @>8800,R1
	SWPB R1
	MOVB @>8800,R1
	SWPB R1
	B *R11

 

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

7 minutes ago, Tursi said:

There's a lot going on in page 1 - what code doesn't work?

 

I don't know if I implemented the ID registers that Matt's original code uses, but most detection code now just tries to run the GPU to change a byte of RAM, and that most certainly works fine in Classic99.

 

JS99er.net has a full F18A implementation as far as I know

 

Hi @Tursi

 

Just completed some new code and it's working now, so F18a detection IS supported

 

Not sure why I was getting lockups but they have gone away now, so must of been my code!

 

Many thanks

  • Like 1
Link to comment
Share on other sites

It looks like the HSGPL code is reading the value of v9938/v9958 status register 4 in order to detect the VDP. This fails on the F18A because it's not unlocked. Status register 4 on the v9938/v9958 is the 'Column register high', which appears to be a strange choice. A more normal choice would be to read status register 1, which has 5 bits for the ID of the VDP. On the F18A, reading status register 1 will also give you the ID, which is >e0. That's how I usually detect the F18A. I think this is described somewhere in this thread.

  • Like 1
Link to comment
Share on other sites

21 minutes ago, Asmusr said:

It looks like the HSGPL code is reading the value of v9938/v9958 status register 4 in order to detect the VDP. This fails on the F18A because it's not unlocked. Status register 4 on the v9938/v9958 is the 'Column register high', which appears to be a strange choice. A more normal choice would be to read status register 1, which has 5 bits for the ID of the VDP. On the F18A, reading status register 1 will also give you the ID, which is >e0. That's how I usually detect the F18A. I think this is described somewhere in this thread.

Maybe not so strange, see 

 

 

  • Like 1
Link to comment
Share on other sites

In addition to what has been mentioned already, @Tursi proposed what I think is the simplest detection.  I can't remember where, but basically run the F18A unlock sequence, then write a small GPU routine into VRAM that will change a specific byte in VRAM.  Send the GPU trigger and read the byte of VRAM to check the value.  I'll see if I can find the routine.

  • Like 1
Link to comment
Share on other sites

I use @Tursi 's approach/routine in newer programs and retrofit an older program or two.  Reason:  a common 9938 detection method (for 40/80 column configuration) BITD was to change VRAM banks via VR#14 and read/write/compare the value; the expectation was that a 9918 would have the same value no matter the bank.  The F18A doesn't have the extra RAM so this method "fails" if you are just trying determine whether the program can run in 80 columns. I like the idea of the identifier/status register for instances where I might want to use the 9938 VRAM for added features. Thanks for sharing that old new trick.

  • Like 2
Link to comment
Share on other sites

6 hours ago, matthew180 said:

In addition to what has been mentioned already, @Tursi proposed what I think is the simplest detection.  I can't remember where, but basically run the F18A unlock sequence, then write a small GPU routine into VRAM that will change a specific byte in VRAM.  Send the GPU trigger and read the byte of VRAM to check the value.  I'll see if I can find the routine.

It's posted 4 posts above yours. ;)

Link to comment
Share on other sites

  • 1 month later...

@matthew180 regarding the F18A bitmap layer, VR31 has a bit BMPPRI which in the documentation (spreadsheet) is described as "Priority over sprites". However, it appears that this is really about priority over tiles  - for TL1 at least - which is good because I want to be able to place a bitmap on top of the tiles. TL2, however, always appears to be displayed on top of the bitmap layer, also if VR51 TILE2_PRI is set to 1. Is there any way to display TL1 + TL2 and a bitmap on top?

  • Like 1
Link to comment
Share on other sites

12 hours ago, Asmusr said:

VR31 has a bit BMPPRI which in the documentation (spreadsheet) is described as "Priority over sprites". However, it appears that this is really about priority over tiles

 

image.thumb.png.c53bb30287176a0899dc54475f3b1eb0.png

 

The register use spreadsheet for V1.9 says "Priority over tiles".  Could be you have an older version for the spreadsheet?  I have attached the latest spreadsheet just in case.

 

12 hours ago, Asmusr said:

Is there any way to display TL1 + TL2 and a bitmap on top?

 

Not currently, no.  Sorry.  Although I think this could be added in the next firmware update.  The BML is only addressed during TL1 processing, so the BML's priority bit is between TL1 and the BML.  Transparent / 0-bit pixels will allow the layer below to show through.

 

Also, the BML does not currently have a priority bit to interact with sprites, but this could be added (or it could inherit TL1's sprite priority bit).  But the layering is pretty complicated already, I'm not sure how much more should be added since it will start to be really hard to reason about what covers what.

 

12 hours ago, Asmusr said:

If the GPU is already executing when a HSYNC trigger occurs, is there any way to return to the code that was executing after the HSYNC routine?

 

If the GPU is not IDLE when the HSYNC trigger occurs, nothing happens and the HSYNC will be missed.  The GPU does not have real interrupts.  If you need exact timing to the HSYNC, then your GPU program needs to run up to the point where it will wait of HSYNC, then execute the IDLE instruction.  This will halt the GPU until the HSYNC is received, or the host CPU issues a GPU trigger, or GPU load and trigger.

 

If you don't want to run IDLE waiting for the HSYNC, you can always poll the horizontal scanline counter in a loop and compare to the previous value (which you would need to track).  You could combine the two methods to wait on HSYNC if it has not occurred since the last loop iteration, or immediately start the next loop if the HSYNC was missed.  Something like this (in a really weird pseudo code):

 

main_loop:
  if last_scanline != scanline then B start_loop
  IDLE
start_loop:
  last_scanline = scanline
  ...

 

 

f18a_register_use.ods

  • Like 1
Link to comment
Share on other sites

2 hours ago, matthew180 said:

Not currently, no.  Sorry.  Although I think this could be added in the next firmware update.  The BML is only addressed during TL1 processing, so the BML's priority bit is between TL1 and the BML.  Transparent / 0-bit pixels will allow the layer below to show through.

 

Also, the BML does not currently have a priority bit to interact with sprites, but this could be added (or it could inherit TL1's sprite priority bit).  But the layering is pretty complicated already, I'm not sure how much more should be added since it will start to be really hard to reason about what covers what.

Thanks for your reply. I have a few changes to make in JS99er, and then I need to think about how to solve this in my current project, which is not as bad as it sounds since I just need TL1+TL2 at the top of the screen and then the remaining screen is covered by a BMP. So I can probably turn off TL2 while the screen is drawn.

 

If there is ever going be an update to the firmware, maybe TILE2_PRI could be repurposed to be about TL2 priority over BMP, and the old purpose of TL2 vs sprite priority would always be considered? I don't think that would break any existing code that I'm aware of.

  • Like 1
Link to comment
Share on other sites

4 hours ago, matthew180 said:

If the GPU is not IDLE when the HSYNC trigger occurs, nothing happens and the HSYNC will be missed.  The GPU does not have real interrupts.  If you need exact timing to the HSYNC, then your GPU program needs to run up to the point where it will wait of HSYNC, then execute the IDLE instruction.  This will halt the GPU until the HSYNC is received, or the host CPU issues a GPU trigger, or GPU load and trigger.

Thanks, I forgot that HSYNC trigger doesn't set the PC to a specified address but just starts the GPU. So the whole question made little sense.

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...