PDA

View Full Version : SMS shooter project



Yharnamresident
08-24-2013, 10:36 PM
Decided I'm making a SMS ROM, so previous thread is no longer relevant.

A shooter, to be exact. Heres some concept art:
http://i.imgur.com/tfj8C1d.png
Palette-swap enemies.


But I'm already running into the main problem with SMS homebrew. Compared to the legendary NES, theres just barely any tutorials and resources for the SMS.

I'm looking for a tutorial that covers sprites. Nothing on SMStributes or SMSpower does so. Can anyone help me out?

Bibin
08-24-2013, 10:46 PM
gradius


If you aren't too set on a horizontal one, I recommend doing a vertical one, as you will hit the per-line sprite limit much less frequently.

TmEE
08-24-2013, 10:59 PM
Sprites use some tiles as BG, it is up to you to make your sprite definitions to use the right tiles.

Yharnamresident
08-24-2013, 11:11 PM
If you aren't too set on a horizontal one, I recommend doing a vertical one, as you will hit the per-line sprite limit much less frequently.I'll take some inspiration from Life Force to achieve that.

Besides, is there any 8-bit or 16-bit shooter that doesn't have slowdown?


Anyways, no progress done. When I search "WLA DX SMS sprites", I get nothing.

Black_Tiger
08-25-2013, 12:29 AM
Besides, is there any 8-bit or 16-bit shooter that doesn't have slowdown?

There are many for both generations, but slowdown itself isn't really a bad thing, especially if it only occurs at special occasions.

Sagaia for SMS has 16-bit quality parallax, large spread of potential ammo and lots of enemies sprites onscreen at a time (as much as Darius Twin for SNES in regular situations). Aleste for SMS throws around as many sprites as Super Aleste and runs even faster.

Most shooters try to push the limit to be intense, but many are balanced so that there isn't any slowdown. I prefer games that have a bit of flicker and slowdown.

TmEE
08-25-2013, 12:36 AM
Anyways, no progress done. When I search "WLA DX SMS sprites", I get nothing.

Sprites work same regardless of assembler. You make your tiles, you put them to VRAM. You make your palettes and you put them to CRAM. You make your pattern/name table/tilemap and put into VRAM and now you have a BG and thun you make your srite definitions and you put them to VRAM and now you got sprites on the BG (or under it). How exactly all of that is done you find in documentation that deals with the VDP, and there's really good stuff about it in here : http://www.smspower.org/Development/Documents

Yharnamresident
08-25-2013, 06:12 AM
But nothing over there is really noob friendly.

Code examples make the learning process so much easier.

I could figure it out with Z80 assembly and VDP documentation, but can't I just take the lazy way out?

Kamahl
08-25-2013, 08:45 AM
but can't I just take the lazy way out?
Nope.

retrospiel
08-25-2013, 10:09 AM
You'll find nothing if you search for "SMS", try searching for "Sega Master System" instead.

I will recommend www.smspower.org as it is THE best place on the web if you're into SMS dev.

Yharnamresident
08-25-2013, 06:21 PM
You'll find nothing if you search for "SMS", try searching for "Sega Master System" instead.

I will recommend www.smspower.org as it is THE best place on the web if you're into SMS dev.

I like popularizing the SMS abbreviation though.

It makes it somewhat obvious, that this is Sega's version of the NES.

Only this one has 4-bit tile glory.


Is there anything on SMStributes that is also useful? I'm trying to see if theres any useful info on that site, besides the unfinished tutorials.

Yharnamresident
08-26-2013, 08:04 AM
I guess I'm not ready for sprites. I wasn't even aware of why the "Hello World" tutorial was filling the VRAM with zeros. Maybe give it a couple more days of "Hello World".

And Chilly if you're reading this, then yes I don't have much experience with console developing. I have wrote games in the past, but that was on the PC with high-level programming languages.

Anyways, more concept art. I'm probably a month away from having anything playable, but its good to dream:
http://i.imgur.com/BeI4EwB.png
Ignore the unrealistic sprites per scanline.

KillerBean2
08-26-2013, 09:03 AM
The VDP documentation on SMSPower.org gives a very good picture of how the sprite system works on the SMS.

Coding in Assembly is not so much a question of knowing what to and what not. It's more about understanding the hardware and its limitations and bending it to your will.

Chilly Willy
08-26-2013, 04:12 PM
And look over demos and games with source. A BUNCH of them! One may be too complex on the graphics, but good for sound and joysticks. Another may be too complex for sound, but good for sprites. And yet another good for seeing how backgrounds work. You just got to read them all, and then read them again until you get it.

Yharnamresident
08-26-2013, 07:06 PM
I have downloaded some source codes, but it all seems pretty alien-like.

Maybe they're not using the same compiler as me.

KillerBean2
08-26-2013, 07:36 PM
Not compiler. Assembler. Unless you're coding in C ;)

tomaitheous
08-26-2013, 08:45 PM
And look over demos and games with source. A BUNCH of them! One may be too complex on the graphics, but good for sound and joysticks. Another may be too complex for sound, but good for sprites. And yet another good for seeing how backgrounds work. You just got to read them all, and then read them again until you get it.

"You must spread some Reputation around before giving it to Chilly Willy again."






I have downloaded some source codes, but it all seems pretty alien-like.

Maybe they're not using the same compiler as me.

Me thinks you need to slow down a bit. If you've never directly handled hardware, without using someone elses libs, you're just gonna have to take your time with this to get familiar. I'm assuming you're learning both assembly (z80) and the supporting hardware itself. I read over the docs at SMSpower and they had quite a bit of info (everything that I would need). Also, find out what assembler such public source code requires (they all have their quirks). I never liked WLA-DX myself, but it's popular enough to have decent support/following for it (and platforms/consoles). The NES dev scene isn't any different. There are three major assemblers in the scene; ca65, nesasm, asm6. And there are other assemblers too, used by nes dev scene.

Yharnamresident
08-26-2013, 09:50 PM
Yes this low level stuff is new to me.

I think I've learned a considerable amount by now though.

But I'm still trying to figure out how to add a sprite to the "Hello World" source code. I want an "A" sprite, right in the middle of the screen:
http://www.smspower.org/maxim/HowToProgram/Lesson1

I think you write a tile to the sprite table in VRAM, and some how add X-Y attributes to it.

tomaitheous
08-26-2013, 10:58 PM
Yes this low level stuff is new to me.

I think I've learned a considerable amount by now though.

But I'm still trying to figure out how to add a sprite to the "Hello World" source code. I want an "A" sprite, right in the middle of the screen:
http://www.smspower.org/maxim/HowToProgram/Lesson1

I think you write a tile to the sprite table in VRAM, and some how add X-Y attributes to it.

Wait, you didn't write your own 'hello world' proggy? You just assembled that source code example??? I think you need to hold off on sprites and master a little bit of the z80 first. Then move onto bg tiles and maps (including palette attributes, palette ram updating, vblank area transfers, maybe some animation of bg tiles, designing around and using mappers, etc). Then move onto sprites. And lastly, sound. If you've never done this stuff before, then it's not just something you can just jump into in a week (your high level language skills really aren't going to help you here). It's a kin to learning how to walk and learning how to compete in a triathlon. One step at a time, is my advice.

To answer your question, you use the sprite attribute table. It's contained on the VDP side of things. Each entry inside the table (a total of 64 entries) holds an attribute setting for a sprite. One of those attributes is which cell to use (8x8, 8x16 paired from two 8x8 cells); it's actually a pointer into vram. The other attributes will be X and Y positionsn.

The spite table is 256 bytes long. The attributes are not setup in a clean sequential type of layout. All of the first 64 entries (bytes) are the Y positions (byte0=Y of sprite 0, byte1=Y of sprite 1, etc). There's a gap in the sprite table that's unused (the SMS lacks sprite priority attributes as well as sprite horizontal/vertical flipping). The X and Pattern attributes start $80 offset into the table. But unlike the Y attributes, the X and P bytes are in groups (byte $80=sprite 0 X position, byte $81=sprite 0 Pattern index, byte $82=sprite 1 X position, byte $83=sprite 1 Pattern index, etc). The pattern index attribute is only 8bits long, so you only have access to 256 cells. But there's a bit in the control register of the VDP that sets which 256 pattern index block that the entire SAT is drawing/pointing from. Individual SAT entries do not have a subpalette attribute, either. All sprites use the same 15 color subpalette. In 8x16 sprite size mode (which can't be selected on a per individual sprite basis) control reg bit is set, all sprite sizes are fixed at that size and the pattern table index bit is irrelevant (since you're accessing sprites as double cells, you already have access to all 512 8x8 patterns/cells). There are a total of 512 patterns to be indexed, but some of the vram must be used for the SAT and the background map. There is a VDP register that points into vram, telling the VDP where this 256 byte SAT is located. You have to set this up, and then write to the corresponding vram address location to make changes to the SAT entries. A vertical position setting of a SAT entry (Y) of $D0 causes the VDP to stop fetching anymore sprites from the table.

That's the gist of it.

Yharnamresident
08-27-2013, 12:39 AM
God, trying to figure this out makes my head hurt.

Say you want a byte to have a Y value of 10.

Its two 4 bit hexadecimals, combined to make an 8-bit integer?

8 4 2 1 + 8 4 2 1 = 128 64 32 16 / 8 4 2 1?

= 0 0 0 0 1 0 1 0

= $0A



But wait, its little endian:

1 2 4 8 16 32 64 128 =

01010000 =

$50? or simply $A0?


brain is nearly reaching its limits

tomaitheous
08-27-2013, 12:55 AM
God, trying to figure this out makes my head hurt.

Say you want a byte to have a Y value of 10.

Its two 4 bit hexadecimals, combined to make an 8-bit integer?

8 4 2 1 + 8 4 2 1 = 128 64 32 16 / 8 4 2 1?

= 0 0 0 0 1 0 1 0

= $0A


Yes, but you don't need to go through all that work. You should get in the habit of at least memorizing hex from $00 to $0f (0 to 15). 4bit hex fits neatly inside a byte, as a pair. $10=16, $20=32,$30=48,$40=64, etc. Memorize enough for both nibbles in a byte, and you'll be fine. Not to memorize all 256 values, just the 16 for the lower nibble and the 16 for the upper nibble. The rest you can do on the fly: $2f = 32+15 = 47. Use a quick calc app to help in the mean time, to go between hex and decimal. Matter of fact (although I don't recommend this), you should be able to use regular decimal notation in almost any assembler. Usually $ is for hex and % is for binary, but 0x0 might be used in some (although that's more popular with higher level languages) and from the old days... 40h (little 'h' at the end) to denote hex value. You should also get into the habit of memorizing single digit hex values in their binary form (for logical operations like AND/OR/XOR/etc).



But wait, its little endian:

1 2 4 8 16 32 64 128 =

01010000 =

$50? or simply $A0?


brain is nearly reaching its limits

No. Not on a nibble basis. Nibbles are stored and used normally, it's when you have pointers or data elements larger than a WORD (two bytes; be careful as WORD doesn't always mean two bytes - depends on the assembler and/or ISA/terminology of the processor). Again, pointers are going to be stored in little endian (or rather, should be). But for your own specified data, you can store it in whatever format you want. If you have data elements the size of 3 bytes, you can store them in big endian format if you want. Though I don't really recommend mixing endians. At least not until you're very comfortable in all of this. None of the SAT data is larger than a word. But the tilemap (BG) data is. Keep that in mind.

Yharnamresident
08-27-2013, 01:23 AM
Okay, first problem is out of the way.

Now, second problem. The sprites use the second colour palette, and mine is empty.

I was assuming its simple enough, to just copy/paste this code, except give it a different address to write to:

;================================================= =============
; Load palette
;================================================= =============
; 1. Set VRAM write address to CRAM (palette) address 0 (for palette index 0)
; by outputting $c000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$c0
out ($bf),a
; 2. Output colour data
ld hl,PaletteData
ld b,(PaletteDataEnd-PaletteData)
ld c,$be
otir

Yharnamresident
08-27-2013, 02:34 AM
Okay thats not a problem. I figured you just need to add another palette line:

PaletteData:
.db $00,$05,$09,$dd,$00,$05,$09,$dd,$00,$05,$09,$dd,$0 0,$05,$09,$dd
.db $39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$3 9,$39,$39,$00
PaletteDataEnd:


The sprite still doesn't show up, but nonetheless I'm satisfied with the progress I made today.

Chilly Willy
08-27-2013, 06:15 PM
No. Not on a nibble basis. Nibbles are stored and used normally,

Well, that's normally the case, but funny thing is, Sony uses little endian nibbles for its graphics. I ran into that when making my port of Basilisk II for the PSP. Virtually everyone uses nibble-wide graphics (16 colors) like this: AB CD EF GH IJ..., but not Sony. They use BA DC FE HG JI... :wtf:

Before I discovered that (and it's not mentioned ANYWHERE), when I ran in 16 color mode, everything looked "fuzzy", and I could never figure out why... until I had this horrific thought and flipped all the nibbles around.

Anywho, the discovery of LE nibbles and seamless striped rendering were my big contributions to PSP homebrew. :D

Yharnamresident
08-29-2013, 12:25 AM
Well, only took a two day break, and I lost all train of thought.

Pretty sure I know why my sprite won't show up though. I have "WriteSpriteLoop" commented out, haven't looked into the proper way of implementing it:

;================================================= =============
; WLA-DX banking setup
;================================================= =============
.memorymap
defaultslot 0
slotsize $8000
slot 0 $0000
.endme

.rombankmap
bankstotal 1
banksize $8000
banks 1
.endro

;================================================= =============
; SDSC tag and SMS rom header
;================================================= =============
.sdsctag 1.2,"Hello World!","SMS programming tutorial program","Maxim"

.bank 0 slot 0
.org $0000
;================================================= =============
; Boot section
;================================================= =============
di ; disable interrupts
im 1 ; Interrupt mode 1
jp main ; jump to main program

.org $0066
;================================================= =============
; Pause button handler
;================================================= =============
; Do nothing
retn

;================================================= =============
; Main program
;================================================= =============
main:
ld sp, $dff0

;================================================= =============
; Set up VDP registers
;================================================= =============
ld hl,VdpData
ld b,VdpDataEnd-VdpData
ld c,$bf
otir

;================================================= =============
; Clear VRAM
;================================================= =============
; 1. Set VRAM write address to 0 by outputting $4000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$40
out ($bf),a
; 2. Output 16KB of zeroes
ld bc, $4000 ; Counter for 16KB of VRAM
ClearVRAMLoop:
ld a,$00 ; Value to write
out ($be),a ; Output to VRAM address, which is auto-incremented after each write
dec bc
ld a,b
or c
jp nz,ClearVRAMLoop

;================================================= =============
; Load palette
;================================================= =============
; 1. Set VRAM write address to CRAM (palette) address 0 (for palette index 0)
; by outputting $c000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$c0
out ($bf),a
; 2. Output colour data
ld hl,PaletteData
ld b,(PaletteDataEnd-PaletteData)
ld c,$be
otir

;================================================= =============
; Load tiles (font)
;================================================= =============
; 1. Set VRAM write address to tile index 0
; by outputting $4000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$40
out ($bf),a
; 2. Output tile data
ld hl,FontData ; Location of tile data
ld bc,FontDataEnd-FontData ; Counter for number of bytes to write
WriteTilesLoop:
; Output data byte then three zeroes, because our tile data is 1 bit
; and must be increased to 4 bit
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Add one to hl so it points to the next data byte
dec bc
ld a,b
or c
jp nz,WriteTilesLoop

;================================================= =============
; Write text to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$38|$40
out ($bf),a
; 2. Output tilemap data
ld hl,Message
ld bc,MessageEnd-Message ; Counter for number of bytes to write
WriteTextLoop:
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Point to next letter
dec bc
ld a,b
or c
jp nz,WriteTextLoop



;================================================= =============
; Write sprites to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$7f
out ($bf),a
; 2. Output tilemap data
ld hl,Sprite
ld bc,SpriteEnd-Sprite ; Counter for number of bytes to write
; WriteSpriteLoop:
; ld a,(hl) ; Get data byte
; out ($be),a
; inc hl ; Point to next letter
; dec bc
; ld a,b
; or c
; jp nz,WriteSpriteLoop





; Turn screen on
ld a,%11000000
; |||| |`- Zoomed sprites -> 16x16 pixels
; |||| `-- Doubled sprites -> 2 tiles per sprite, 8x16
; |||`---- 30 row/240 line mode
; ||`----- 28 row/224 line mode
; |`------ VBlank interrupts
; `------- Enable display
out ($bf),a
ld a,$81
out ($bf),a

; Infinite loop to stop program
Loop:

jp Loop





;================================================= =============
; Data
;================================================= =============

Message:
.dw $00,$01,$00
MessageEnd:

Sprite:
.dw $0a,$2f,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
;----------------------------------
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
;----------------------------------
.dw $0a,$01,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00


SpriteEnd:

PaletteData:
.db $00,$05,$09,$dd,$00,$05,$09,$dd,$00,$05,$09,$dd,$0 0,$05,$09,$dd
.db $39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$3 9,$39,$39,$00
PaletteDataEnd:

PaletteData2:
.db $06,$08,$11,$15
PaletteDataEnd2:

; VDP initialisation data
VdpData:
.db $04,$80,$84,$81,$ff,$82,$ff,$85,$ff,$86,$ff,$87,$0 0,$88,$00,$89,$ff,$8a
VdpDataEnd:

FontData:
.db $ff,$00,$00,$00,$ff,$00,$00,$00,$ff,$00,$00,$00,$f f,$00,$00,$00
.db $ff,$00,$00,$00,$ff,$00,$00,$00,$ff,$00,$00,$00,$f f,$00,$00,$00
.db $ff,$00,$00,$ff,$ff,$00,$00,$ff,$ff,$00,$00,$ff,$f f,$ff,$00,$00
.db $ff,$00,$00,$ff,$ff,$00,$00,$ff,$ff,$00,$00,$ff,$f f,$ff,$00,$00

FontDataEnd:

tomaitheous
08-29-2013, 06:57 PM
Well, only took a two day break, and I lost all train of thought.

Pretty sure I know why my sprite won't show up though. I have "WriteSpriteLoop" commented out, haven't looked into the proper way of implementing it:

;================================================= =============
; WLA-DX banking setup
;================================================= =============
.memorymap
defaultslot 0
slotsize $8000
slot 0 $0000
.endme

.rombankmap
bankstotal 1
banksize $8000
banks 1
.endro

;================================================= =============
; SDSC tag and SMS rom header
;================================================= =============
.sdsctag 1.2,"Hello World!","SMS programming tutorial program","Maxim"

.bank 0 slot 0
.org $0000
;================================================= =============
; Boot section
;================================================= =============
di ; disable interrupts
im 1 ; Interrupt mode 1
jp main ; jump to main program

.org $0066
;================================================= =============
; Pause button handler
;================================================= =============
; Do nothing
retn

;================================================= =============
; Main program
;================================================= =============
main:
ld sp, $dff0

;================================================= =============
; Set up VDP registers
;================================================= =============
ld hl,VdpData
ld b,VdpDataEnd-VdpData
ld c,$bf
otir

;================================================= =============
; Clear VRAM
;================================================= =============
; 1. Set VRAM write address to 0 by outputting $4000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$40
out ($bf),a
; 2. Output 16KB of zeroes
ld bc, $4000 ; Counter for 16KB of VRAM
ClearVRAMLoop:
ld a,$00 ; Value to write
out ($be),a ; Output to VRAM address, which is auto-incremented after each write
dec bc
ld a,b
or c
jp nz,ClearVRAMLoop

;================================================= =============
; Load palette
;================================================= =============
; 1. Set VRAM write address to CRAM (palette) address 0 (for palette index 0)
; by outputting $c000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$c0
out ($bf),a
; 2. Output colour data
ld hl,PaletteData
ld b,(PaletteDataEnd-PaletteData)
ld c,$be
otir

;================================================= =============
; Load tiles (font)
;================================================= =============
; 1. Set VRAM write address to tile index 0
; by outputting $4000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$40
out ($bf),a
; 2. Output tile data
ld hl,FontData ; Location of tile data
ld bc,FontDataEnd-FontData ; Counter for number of bytes to write
WriteTilesLoop:
; Output data byte then three zeroes, because our tile data is 1 bit
; and must be increased to 4 bit
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Add one to hl so it points to the next data byte
dec bc
ld a,b
or c
jp nz,WriteTilesLoop

;================================================= =============
; Write text to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$38|$40
out ($bf),a
; 2. Output tilemap data
ld hl,Message
ld bc,MessageEnd-Message ; Counter for number of bytes to write
WriteTextLoop:
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Point to next letter
dec bc
ld a,b
or c
jp nz,WriteTextLoop



;================================================= =============
; Write sprites to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$7f
out ($bf),a
; 2. Output tilemap data
ld hl,Sprite
ld bc,SpriteEnd-Sprite ; Counter for number of bytes to write
; WriteSpriteLoop:
; ld a,(hl) ; Get data byte
; out ($be),a
; inc hl ; Point to next letter
; dec bc
; ld a,b
; or c
; jp nz,WriteSpriteLoop





; Turn screen on
ld a,%11000000
; |||| |`- Zoomed sprites -> 16x16 pixels
; |||| `-- Doubled sprites -> 2 tiles per sprite, 8x16
; |||`---- 30 row/240 line mode
; ||`----- 28 row/224 line mode
; |`------ VBlank interrupts
; `------- Enable display
out ($bf),a
ld a,$81
out ($bf),a

; Infinite loop to stop program
Loop:

jp Loop





;================================================= =============
; Data
;================================================= =============

Message:
.dw $00,$01,$00
MessageEnd:

Sprite:
.dw $0a,$2f,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
;----------------------------------
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
;----------------------------------
.dw $0a,$01,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00
.dw $00,$00,$00,$00,$00,$00,$00,$00


SpriteEnd:

PaletteData:
.db $00,$05,$09,$dd,$00,$05,$09,$dd,$00,$05,$09,$dd,$0 0,$05,$09,$dd
.db $39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$39,$3 9,$39,$39,$00
PaletteDataEnd:

PaletteData2:
.db $06,$08,$11,$15
PaletteDataEnd2:

; VDP initialisation data
VdpData:
.db $04,$80,$84,$81,$ff,$82,$ff,$85,$ff,$86,$ff,$87,$0 0,$88,$00,$89,$ff,$8a
VdpDataEnd:

FontData:
.db $ff,$00,$00,$00,$ff,$00,$00,$00,$ff,$00,$00,$00,$f f,$00,$00,$00
.db $ff,$00,$00,$00,$ff,$00,$00,$00,$ff,$00,$00,$00,$f f,$00,$00,$00
.db $ff,$00,$00,$ff,$ff,$00,$00,$ff,$ff,$00,$00,$ff,$f f,$ff,$00,$00
.db $ff,$00,$00,$ff,$ff,$00,$00,$ff,$ff,$00,$00,$ff,$f f,$ff,$00,$00

FontDataEnd:



One of your problems, is that you have the sprite pattern table index set to 1 - but you have no tile data written there (vram was cleared).
See here:

; VDP initialisation data
VdpData:
.db $04,$80,$84,$81,$ff,$82,$ff,$85,$ff,$86,$ff,$87,$0 0,$88,$00,$89,$ff,$8a
VdpDataEnd:

Change it so that it accesses the first 256 patterns of vram. Or write some tile data to the second pattern block area.

retrospiel
08-30-2013, 10:30 AM
I hope you stick with this, really looking forward to a new SMS homebrew game.

PS: Before you give up let me know, I remember that haraldoop ported BASIC to SMS so that might still be an option.

Yharnamresident
08-30-2013, 07:27 PM
I hope you stick with this, really looking forward to a new SMS homebrew game.

PS: Before you give up let me know, I remember that haraldoop ported BASIC to SMS so that might still be an option.This may take awhile though


There are only certain parts of the day, where I can become focused enough to work in assembly.

KillerBean2
08-30-2013, 09:27 PM
Some really good advice:

Write tons and tons of comments in your code. Seriously, you can't write too much!

A few days ago I took a look at some of the stuff I wrote a year ago, and it was complete jiberish :D

Yharnamresident
08-30-2013, 10:39 PM
I'll try to remember that.


I think the biggest problem, is becoming focused enough to work in assembly. This is tough sh!t.

Because we're not practically working in binary. We literally are.

I think around 24:00 PM, is when I can become focused enough to work on this project.

Stef
08-31-2013, 04:00 PM
Why don't you try to develop on the sega megadrive instead ? the hardware is really straightforward and more powerful than SMS. Also you ave more facilities to develop as you can directly use Basic or C languages. Basic could be a bit limiting for big project but C is enough to handle complexes games.

Yharnamresident
08-31-2013, 07:18 PM
It won't be smart to change my platform now. I've already learned a ton about the SMS hardware and Z80 assembly.

Stef
09-01-2013, 07:35 PM
What you learnt about SMS hardware is not lost as MD work in a similar way (even simpler on some way) but yeah, it's up to you.
If i told you that is that learning both Z80 assembly and SMS hardware is imo a very hard task when you don't have any experience with both assembly and video game system... using a well known language as C or basic would have make things far easier for you :)

Moirai
09-01-2013, 09:38 PM
I say move the project over to Saturn :P

Yharnamresident
09-01-2013, 10:10 PM
I say move the project over to Saturn :PI was gonna have a compilation disc on the Saturn, of my SMS shooters.

Yharnamresident
09-02-2013, 07:49 AM
I say move the project over to Saturn :PI have considered jumping ship though. I can find gallons of information, and tutorials on NES homebrew.


I've finally announced one of the problems with my sprite source code:


;================================================= =============
; Load tiles (font)
;================================================= =============
; 1. Set VRAM write address to tile index 0
; by outputting $4000 ORed with $0000
ld a,$00
out ($bf),a
ld a,$40
out ($bf),a
; 2. Output tile data
ld hl,FontData ; Location of tile data
ld bc,FontDataEnd-FontData ; Counter for number of bytes to write
WriteTilesLoop:
; Output data byte then three zeroes, because our tile data is 1 bit
; and must be increased to 4 bit
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Add one to hl so it points to the next data byte
dec bc
ld a,b
or c
jp nz,WriteTilesLoop

;================================================= =============
; Write text to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$38|$40
out ($bf),a
; 2. Output tilemap data
ld hl,Message
ld bc,MessageEnd-Message ; Counter for number of bytes to write
WriteTextLoop:
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Point to next letter
dec bc
ld a,b
or c
jp nz,WriteTextLoop



;================================================= =============
; Write sprites to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$7f
out ($bf),a
; 2. Output tilemap data
ld hl,Sprite
ld bc,SpriteEnd-Sprite ; Counter for number of bytes to write
WriteSpriteLoop:
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Point to next letter
dec bc
ld a,b
or c
jp nz,WriteSpriteLoop




It seems when I load the sprites into memory, it overwrites the tile data(not tilemap) instead.

It could be doing this, because of what tomaitheous said of the VDP sprite initialization isn't set up correct.

Maxim makes no mention of what hes doing with the VDP initialization: http://www.smspower.org/maxim/HowToProgram/Initialisation?sid=66430baebb748a65b5ba1af0409a8c6 5

I'll go through the VDP documentation again, to see if I can make any connections of how those bytes are setting up the VDP.

Yharnamresident
09-03-2013, 09:48 AM
I hate to triple-post, but I need to prove I've finally learned sprites.

You see that black object, halfway down the screen? thats a sprite.


Otherwise, does anyone wanna check out my awesome pixel art skills?

Pretend you're a ship, flying through a hot cavern:
https://docs.google.com/file/d/0B8yyQQd93Xz6MHpKU1Y2bUZCRU0/edit?usp=sharing

KillerBean2
09-04-2013, 08:37 AM
Was it VDP Register #6 that was the problem?

In the "Hello World" tutorial, the sprite table is placed at $5F00 in stead of the normal $3F00.

That little part also had me puzzled when I tried to learn how to use sprites :D

Yharnamresident
09-04-2013, 11:36 AM
Was it VDP Register #6 that was the problem?

In the "Hello World" tutorial, the sprite table is placed at $5F00 in stead of the normal $3F00.

That little part also had me puzzled when I tried to learn how to use sprites :D
Well not sure if I corrected that or not, but I seem to be loading sprites fine now.


What the problem was, and still is, is that when I load sprites, it only inserts it into the odd numbers in memory. I.E., it loads a byte, skips a byte in memory, then loads another byte:
http://i.imgur.com/QLqMjZm.png

I have no idea why its skipping the even parts in memory. Heres my code:


;================================================= =============
; Write sprites to name table
;================================================= =============
; 1. Set VRAM write address to name table index 0
; by outputting $4000 ORed with $3800+0
ld a,$00
out ($bf),a
ld a,$7f
out ($bf),a
; 2. Output tilemap data
ld hl,Sprite
ld bc,SpriteEnd-Sprite ; Counter for number of bytes to write
WriteSpriteLoop:
ld a,(hl) ; Get data byte
out ($be),a
inc hl ; Point to next letter
dec bc
ld a,b
or c
jp nz,WriteSpriteLoop


Sprite:
.dw $89,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2 f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f, $2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2 f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f,$2f
SpriteEnd:

KillerBean2
09-04-2013, 12:01 PM
That's because you have the data listed as words in stead of bytes. Replace ".dw" with ".db" :)

Yharnamresident
09-04-2013, 12:19 PM
Dammit, I knew I should be aware of what those meant.

I kept thinking it stood for "database", my SQL knowledge is interfering.


Anyways, thats the only progress I'm gonna make today. I can't code while running off of 6 hours of sleep.

But I gotta know for tomorrow, does the SMS update the screen automatically? or do you gotta call some "re-paint" function?

KillerBean2
09-04-2013, 12:46 PM
I doesn't work like that. The VDP just draws whatever's in the VRAM/CRAM. It shows the change as soon as it reaches the place where you made it... if that makes sense.

That's also why you can mess things up, if you write to the VRAM during active display.

tomaitheous
09-04-2013, 09:47 PM
Was it VDP Register #6 that was the problem?

In the "Hello World" tutorial, the sprite table is placed at $5F00 in stead of the normal $3F00.

That little part also had me puzzled when I tried to learn how to use sprites :D

Vram only goes to #$3fff (16k).


But I gotta know for tomorrow, does the SMS update the screen automatically? or do you gotta call some "re-paint" function?
Whatever changes you made to the VDP, remain static until you make further changes. So no, you don't need to keep re-updating the same data every screen - unless they be changes.


Well not sure if I corrected that or not, but I seem to be loading sprites fine now.
Loading sprite cells or sprite SAT entries? If you didn't change reg #6 or didn't write new cells to the sprite cell area designated by current reg 6 value (pattern block 2), then the SAT entry won't show a sprite object onscreen (because vram was cleared and all pixels in the pattern block 2 are transparent).

Yharnamresident
09-05-2013, 02:28 AM
SAT entries.

So the Master System only has two shades of grey, so I can't get my ship my desired colour.

But I'm satisfied with what I got, yet no sprites are final.

Anyone wanna take a look?:
https://docs.google.com/file/d/0B8yyQQd93Xz6YUhESmVLX1JKa2M/edit?usp=sharing

After this, I'm gonna take a break from sprites, to figure out how the SMS updates and so on.

KillerBean2
09-05-2013, 08:12 AM
Vram only goes to #$3fff (16k).

True, I'm babbling. Had the patterns and SAT mixed up (ironically). The sprite table goes to $3F00 (always!), but in the "Hello World" tutorial the sprites use the tiles at $2000 in stead of the ones at $0000, right?


After this, I'm gonna take a break from sprites, to figure out how the SMS updates and so on.

The VDP redraws the screen 60 or 50 (NTSC/PAL) times per second. If you have the frame interrupt enabled (bit 5 of register $01), one will be triggered each time the VDP has finished drawing a frame, and you'll have the time span of the vertical blanking to make changes to registers, VRAM and CRAM. The frame interrupt is very useful.

Yharnamresident
09-05-2013, 01:53 PM
The SMSpower tutorial talks about interrupts I think.


So this is how you do "if statements" in Z80, looks pretty simple:
http://www.andreadrian.de/oldcpu/Z80_number_cruncher.html#mozTocId370017

god, looking at that C code is so refreshing. Its like seeing daylight, after 5 years of being stuck in a bomb shelter.

tomaitheous
09-05-2013, 11:31 PM
The SMSpower tutorial talks about interrupts I think.


So this is how you do "if statements" in Z80, looks pretty simple:
http://www.andreadrian.de/oldcpu/Z80_number_cruncher.html#mozTocId370017

god, looking at that C code is so refreshing. Its like seeing daylight, after 5 years of being stuck in a bomb shelter.

That's only because you don't have enough time spent with assembly (any processor). 'IF' statements are just made up of compare logic. Sometimes there are short cuts (such as loading an initial value into register that yields ZERO, can set a flag), and other times you just have to write multiple compare steps. It's all about the status FLAGs. Comparing, subtracting, adding, shifting, logic operations, etc all yield results in the status FLAG register. You just have to pay attention as to what instructions effect this flag (it can be different on other processors). Some processors have quite a few flags, and multiple flags can be set depending on an action. For other processors, they are more limited and thus you have to write 'fall though' test code to check something multiple times (case logic).

Compare instructions are usually the same as subtraction opcodes, except nothing is changed or updated other than the status flag. This is desirable because you might want to compare one register or value against quite a few different values; Is A>1, is A=0, is A<45, is A>88, etc. I often write short hand notes as C code, next to my assembly. It's faster than writing out english or language comments and it's faster to read and understand as well.

I've done sooo much 65x, that my z80 is rusty (z80 was my first 8bit processor that I learned assembly one, after learning x86 assembly). It won't seem so convoluted and/or complex, once you get the hang of it. And once you get good enough, you can write high level macros for non essential code (usually non speed sensitive areas).

Also, don't forget this one aspect: while you only have vblank to update the VDP - you have the whole frame to do in game logic. Don't try to fit every thing into vblank area. You'll run out of cpu resource real quick. Instead, do the game logic after vblank necessary code. Just buffer whatever changes you need, to fall on the next vblank. That way you maximize the full potential of the CPU. Yes, you'll have a 1 frame delay. But it's such a small interval and a lot of old systems did this; no one complained.

There's also a dirty little trick you can do to double the speed of your processor... per se. Almost all retro games on such consoles ran at 60/50 fps (home computers did half frame rate because the cpu or blitter need to do more heavy lifting in comparison). It's possible to run game logic at half frame rate, but movement and animation at full frame rate. This doesn't exactly give you double cpu resource as you still need to do frame updates on every frame, but game logic usually takes much cpu resource, so it does free up more than usually. Probably somewhere half way in between.

Yharnamresident
09-09-2013, 08:21 AM
This project is frozen. Not dead, frozen.

I just don't think I'm ready for this low-level stuff. I'm gonna return to it in a couple months.

So I'm moving this project over to PlayStation Vita, the object-oriented C# is just mouth watering.

Then after its done, I'll try hard to port it to the SMS.

Remember I still have interest in SMS homebrewing. The 4-bit tiles and FM sound, make the SMS the obvious choice for 8-bit homebrew.

I think learning more high-level game development, could somewhat help me understand low-level game logic a bit more.

TmEE
09-09-2013, 08:43 AM
the high level stuff will only help you with things like game logic and management, however it will not help a single bit with stuff you are stuck with right now :P