Using the new features

Discuss game and other programming topics not specifically covered in another forum

Moderator: Programming Moderators

User avatar
Sludge
Posts: 30
Joined: Wed May 31, 2017 12:37 am
Location: England

Using the new features

Postby Sludge » Tue Dec 04, 2018 2:23 pm

I'm writing a new game for the Spectrum in MC and have left some space spare for use with the Nexts new features.

I have set the background to INK 0, PAPER 0, BRIGHT 0 (0) and want this to be transparent to allow layer 2 to be visible.

I also want INK 0, PAPER 0, BRIGHT 1 (65) to be transparent as well, is that possible?

What kind of Out commands do I need to use to activate the transparency?

Each screen will use a different BMP background, how do I load that file using MC?

Alcoholics Anonymous
Posts: 397
Joined: Mon May 29, 2017 7:00 pm

Re: Using the new features

Postby Alcoholics Anonymous » Tue Dec 04, 2018 4:00 pm

There is one transparent colour held in nextreg 0x14 (see https://www.specnext.com/tbblue-io-port-system/ ). You can write into the registry using a new z80n instruction "nextreg 0x14,a" or "nextreg 0x14,n" or you can go a longer way by using standard OUTs. First OUT to port 0x243b with the selected register (0x14 eg) then IN or OUT to port 0x253b to read or write the value. Because this is a non-atomic two-step process, your interrupt routine must preserve the selected register in port 0x243b if it changes it during the isr.

The transparent colour is matched against the final 9-bit colour of layer 2 or the ULA; it's an 8-bit value (nextreg 0x14 only stores 8 bits) matched against the top 8-bits of the 9-bit colour so that the third B bit of the RRRGGGBBB colour is not part of the match. That is, two 9-bit colours match the transparent colour. Sprite transparency is handled separately via nextreg 0x4b because sprites have a palette offset feature.

Each layer (ula, sprite, layer 2) has a 256-entry palette through which the nominal 8-bit index is looked up to determine the final 9-bit colour (see nextreg 0x40-0x44 for how palettes are changed). Speaking about the ULA, the machine will boot up so that the ULA palette will be the same as the standard zx colours. IIRC (just in case I am mis-remembering :) ), inks 0-7 are in palette entries 0-7, bright inks 0-7 are in palette entries 8-15, paper 0-7 is in 16-23 and bright paper in 24-31. Border colour goes through paper 0-7 in standard ULA mode. ULAnext, which is similar idea to ULA+, changes this somewhat but since this is spectrum compatible, I won't mention it further.

So if you want INK 0 + BRIGHT 0 and INK 0 + BRIGHT 1 to be transparent you have to change the ULA palette entries 0 and 8 to the transparent colour in nextreg 0x14. Likewise if you want PAPER 0 + BRIGHT 0 and PAPER 0 + BRIGHT 1 to be transparent you have to change the ULA palette entries 16 and 24 to the transparent colour.

In nextreg 0x43 make sure the active palette is ULA palette 0 and make sure you will be writing to ULA palette 0. In nextreg 0x40 select the palette index. And through nextreg 0x41 or 0x44 change the colour at the palette index.

I assume your bmp background will be a layer 2 screen? This is the 256x192 screen with each pixel a different colour (and is scrollable should you need that). The screen requires 48k memory and occupies three consecutive 8k pages. Normally it is located in pages 18-20 since the 128k spectrum occupies 16k banks 0-7 (pages 0-15) and nextzxos additionally takes bank 8 (pages 16 and 17). The current location of layer 2 can be read/written using nextreg 0x12. Note a 16k BANK number is written there, not a page number so layer 2 must start on an even 8k page (the default is 9 so it starts at page 18 normally). Layer 2 must also be completely contained in the first 512k chip so must be completely contained in pages 0-31. You shouldn't have to change where it is and can assume it starts at page 18.

So you must load your bmp into 48k occupying pages 18-20 assuming you don't change any defaults. The layer 2 screen organization is linear left to right, top to bottom with each byte holding an 8-bit index colour. This index is looked up through the layer 2 palette to find out the final 9-bit colour for a particular index. Your image will select 256 colours from the 9-bit RRRGGGBBB colour space and must load those colours into the layer 2 palette in a similar way as done for the ULA above. Keep in mind, you may want one index to be the transparent colour and two 9-bit final colours are reserved for the transparent colour in nextreg 0x14. There is a sort of standard forming where a layer 2 screen consists of 512 bytes of 9-bit palette values (or 256 bytes of 8-bit palette values) followed by the 48k image.

You can build programs that contain all of the required zx next memory space as a .nex or .snx (extended sna) with tools like z88dk or nexbuild. In these cases your program can already contain the image in pages 18-20 when it is loaded.

However, I think you have in mind distributing in a format for the zx with an extra for the zx next. If your program is a tap file you can go two ways:

1. Keep the tap file as is and distribute an extra file containing your layer 2 image. Then on the zx next you would have two files on sd card: "game.tap" and "game-image.bin". You can load "game-image.bin" into pages 18-20 at runtime using the esxdos api. When the user runs "game.tap" the current directory will be the one "game.tap" exists in. Then you can open the "game-image.bin" file and read that into pages 18-20 8k at a time so you can change pages between each 8k chunk. Then close the file. If you are unfamiliar with the esxdos api, it is documented in nextzxos_api.pdf at https://gitlab.com/thesmog358/tbblue/tr ... s/nextzxos . The esxdos api is described toward the end of the document.

The zx next's 64k address space is divided into eight mmus. So mmu0 covers 0-8k, mmu1 8k-16k, ..., mmu7 56k-64k. The esxdos api requires the rom to remain present in the bottom 16k so you won't be able to get esxdos to load anything down there. So to make pages 18-20 you must use an mmu outside the bottom 16k. I might overlay the 0x4000-0x5fff area which is mmu2. Place page 18 into mmu2, load 8k there, place page 19 into mmu2, load another 8k, place page 20 into mmu2 load the last 8k. Restore page 10 into mmu2 when done (page 10 is the first 8k of bank 5 which holds the ula screen). Some assemblers have special mmu pseudo-instructions to make this easy (eg z88dk has "mmu0 n", "mmu1 n" etc) but these are aliases for a longer winded nextreg instruction. The mmus are nextreg registers see nextreg 0x50-0x57 ( https://www.specnext.com/tbblue-io-port-system/ ).

2. Add the layer 2 image to the end of your tap file in three 8k chunks. If you're on the zx next, your load process loads that into layer 2. On the next, the tap file is a container format and there is a separate api for seeking, etc on the currently open tap file. You won't have to do any of that since after your program loads, the tap file pointer will be pointing at the 8k chunks for your layer 2 image. You can continue to load those via the standard rom tape routines. You would load 8k at a time to pages 18-20 as above using mmu instructions between.

Once you have the layer 2 image loaded and you've set the layer 2 palette, you have to enable layer 2. You will want to set layer order in nextreg 0x15 so that the ULA is on top of layer 2. You can see various layer orderings in the documentation for nextreg 0x15. Eg, SLU means sprites on top of layer 2 on top of ULA.

To turn on layer 2, you have to write to port 0x123b:

Code: Select all

define(`__IO_LAYER_2_CONFIG', 0x123b)

define(`__IL2C_ENABLE_LOWER_16K', 0x01)      # Layer 2 enable vram visible in lower 16k in write only mode
define(`__IL2C_SHOW_LAYER_2', 0x02)          # Layer 2 enable display of layer 2 (reg 18 defines first 16k bank)
define(`__IL2C_SELECT_SHADOW_BUFFER', 0x08)  # Layer 2 choose shadow buffer for lower 16k (reg 19 defines first 16k page)
define(`__IL2C_BANK_SELECT_MASK', 0xc0)      # Layer 2 vram bank 0-2 visible in lower 16k
define(`__IL2C_BANK_SELECT_0', 0x00)
define(`__IL2C_BANK_SELECT_1', 0x40)
define(`__IL2C_BANK_SELECT_2', 0x80)
Just "out 0x123b,0x02" will turn on layer 2.

Well that's quite a lot of info. It all makes sense and is fairly straightforward once you've got past the initial learning curve though :).

Ped7g
Posts: 14
Joined: Mon Jul 16, 2018 7:11 pm

Re: Using the new features

Postby Ped7g » Tue Dec 04, 2018 7:03 pm

Aren't the border colours 128..135?

Alcoholics Anonymous
Posts: 397
Joined: Mon May 29, 2017 7:00 pm

Re: Using the new features

Postby Alcoholics Anonymous » Tue Dec 04, 2018 7:57 pm

I'm pretty sure border colour always comes from paper 0-7 which is at those indices mentioned for standard ULA mode.

ULAnext mode has the paper colours starting from 128 so in that case border would come from 128 and up to 135 depending on how many bits are given to ink out of the attr byte.

User avatar
Sludge
Posts: 30
Joined: Wed May 31, 2017 12:37 am
Location: England

Re: Using the new features

Postby Sludge » Wed Dec 05, 2018 10:37 pm

Quite a bit to take in there. Gonna have to have a proper sit down and read the related stuff and try and get my head round it all.


Who is online

Users browsing this forum: No registered users and 0 guests