Archive for the homebrew Category

Far calls

Posted in homebrew on August 14, 2014 by pcedev

I filled up my first lib bank (the first non-fixed mapped library bank). I had a far call setup from main/fixed to far lib stuffs, but now that I’m on my second lib bank I needed to figured out a way how to handle call far routines from lib bank 1 and vice versa.

The problem wasn’t so much a problem, until I needed the functionality of nesting far calls. I.e. call in banks, between banks, as if they were some linear mapped large bank. I’ve limited the far code to 8k, with 32k for data, and top 8k for fixed bank stuffs. The macro I have setup, helps keep the code clean – but otherwise it just stores bank:word -> A:X:Y and then JSRs to a fixed bank function. The fixed function basically pushed the return bank# and address onto the real stack. So, I can basically nest up to ~51 far calls. The overhead isn’t that bad:

;##########################################################################
;………………………………………………………………..
;
DoFarCall:

sta FarJSR+2
tma #$02
pha

lda FarJSR+2
tam #$02
stx FarJSR+0
sty FarJSR+1

jsr .CallFar

pla
tam #$02
rts

.CallFar
jmp [FarJSR]

rts
;END_SUB

Of course, routines inside a lib bank don’t need far calls (I’ll probably add testing logic in the macro, so it’ll automatically detect and use a near call or a far call. All on the Assembler program side; no cpu code used). So things are arranged optimally. For this game, a 16K far code page + 24k data page layout would probably be better. But for now, I’ll stick with the 8k far code page. Meh, I’ll probably end up changing it later on. So it goes..

Advertisements

VDC secret registers

Posted in hacks, homebrew on August 14, 2014 by pcedev

If you’ve coded for the PCE, especially in assembly and directly accessed the video hardware, you should have noticed that there’s a gap in the register list. Regs $03 and $04 are skipped. A couple of years back, with some discovery by tests Charles Macdonald had done, I eventually figured out that the key to using these registers – is to set the VRAM READ pointer. Depending on the bits set in the WORD buffer of that register, reading from $03 (IIRC, one the regs), enables or disables certain things of the VDC. It has minimal application outside of a few demo effects (mostly distortion type). But recently, it got me thinking. What I never tested… was if I could get the VDC to re-read any of the X/Y/CR/etc regs from the buffer – via these regs. Would be kinda neat for horizontal split screen scrolling and such, if possible. Just a note for when I get my console hardware back up and running.

Posted in homebrew on August 13, 2014 by pcedev

Got the object/NPC/enemy scrolling code done (screen to screen scrolling), ala Neutopia style. So the old screen as well as the old objects, scroll out as the new screen and new objects scroll in. Zelda for nes, cheats this. It removes all sprites, then scrolls. When the new screen scrolls in, the enemies then spawn. I’m going with a neutopia style instead of the zelda style.

Anyway. I have room/screen data, sprite sheets, attributes, etc. When a screen is loaded, NPCs/enemies load up. For right now they just dance in place. What I’m working on next is enemy AI. This will be a little bit new for me (for this style), rather than scripted or side view stuffs. Top down maze style AI?

Posted in homebrew on August 13, 2014 by pcedev

Btw TOUKO, I’m loving this ‘processing queue’ thingy. It makes adding test processes soo easy, fast, and nice/clean. I’m glad I took the extra time to write it. It’s already paid itself off in dev time for other parts of the game development.

sprite animation sheets

Posted in homebrew on August 13, 2014 by pcedev

‘Been working on animation sheets, and code to read/build SAT entries from them. There’s quite a bit of indirection there. I’ve been thinking of ways to optimize them:

NPCList:
.dw _Enemy0
.db bank(_Enemy0),00
.dw _Enemy1
.db bank(_Enemy1),00
.dw _Enemy2
.db bank(_Enemy2),00
.dw _Enemy2
.db bank(_Enemy2),00
.dw _Enemy3
.db bank(_Enemy3),00
.dw _Enemy4
.db bank(_Enemy4),00

_Enemy0

.dw .Up
.dw .Down
.dw .Right
.dw .Left
.dw .Death
.dw .Attack
.dw .Damaged

.Up
.dw .Up.Frame0, .Up.Frame1, $ffff

.Up.Frame0
; duration of frame. This gets copied to object handler
.db $04
; X offset (signed)
.dw $0020
; Y offset (signed)
.dw $0040
; Pattern
.dw $364
; Attrib
.dw (SIZE16_16|PRIOR_H|SPAL2)
.Up.Frame1
.db $04
.dw $0020
.dw $0040
.dw $366
.dw (SIZE16_16|PRIOR_H|SPAL2)

.Down
.dw .Down.Frame0, .Down.Frame1, $ffff

.Down.Frame0
; duration of frame. This gets copied to object handler
.db $04
; X offset (signed)
.dw $0020
; Y offset (signed)
.dw $0040
; Pattern
.dw $360
; Attrib
.dw (SIZE16_16|PRIOR_H|SPAL2)
.Down.Frame1
.db $04
.dw $0020
.dw $0040
.dw $362
.dw (SIZE16_16|PRIOR_H|SPAL2)

.Right
.dw .Right.Frame0, .Right.Frame1, $ffff

.Right.Frame0
; duration of frame. This gets copied to object handler
.db $04
; X offset (signed)
.dw $0020
; Y offset (signed)
.dw $0040
; Pattern
.dw $368
; Attrib
.dw (SIZE16_16|PRIOR_H|SPAL2)
.Right.Frame1
.db $04
.dw $0020
.dw $0040
.dw $36a
.dw (SIZE16_16|PRIOR_H|SPAL2)

.Left
.dw .Left.Frame0, .Left.Frame1, $ffff

.Left.Frame0
; duration of frame. This gets copied to object handler
.db $04
; X offset (signed)
.dw $0020
; Y offset (signed)
.dw $0040
; Pattern
.dw $368
; Attrib
.dw (H_FLIP|SIZE16_16|PRIOR_H|SPAL2)
.Left.Frame1
.db $04
.dw $0020
.dw $0040
.dw $36a
.dw (H_FLIP|SIZE16_16|PRIOR_H|SPAL2)

.Death

.Attack

.Damaged

In the above standard example, there are three layers of pointers that you need to load there. I was thinking, since most/all of the data inside the main entry are just offsets to other parts, that I might just store the offset (add the offset to the base pointer to move along the list).

But the other idea that I had, was to build the sheet as code itself. It would jump to the specific addresses (based on tables) by using a few shared variables. It could write direct to SATB in the VDC, or to a local SAT in sys RAM.

How do you guys do your sprite sheets? (the animation tables, not the sprite pixel data itself).

Posted in homebrew on August 8, 2014 by pcedev

So I decided to use a Process queue for this little game as well, instead of a large case/select list. The queue is pretty much just an index list, to a jump table. Up to 127 entries. The high bit for the index (8bit) is for ‘sleep’ mode of the process (when they need to be temporarily disabled). Processes can remove themselves from the queue, if they’re non infinite types (either by completed tasks or by frame #/counter). Certain higher level Processes can put low priority Processes into sleep mode (like disabling controls for scripted movement, loading a next area/dungeon/etc). There’s also a frame counter to delay the start of a Process once it’s put into the queue.

The overhead is pretty tiny. And reordering the index list and using an early terminator value helps speed up parsing and working with the index. I can prioritize which order the processes get executed simply by the order they are in the index/list, which is also nice.

For instance, I initialized the first area of the game with these macs

AddProcess #READ_IO.process
AddProcess #SEGMOVE.process
AddProcess #FRAMEUPDATE.process
AddProcess #SHOWPLAYER.process

SEGMOVE.process handles the sprite movement and collision detection. When I want to scroll to the next screen (Neutopia style), I add DOSCROLL.process to the queue and put SEGMOVE.process into sleep. Same with WARP.process (stairs/doors/etc).

Maybe it’s overkill, but it just feels more structured and is easier to follow along. I dunno. In debugging, I can see what processes are on the list too – rather than stepping through a large and/or multiple case/select lists.

I’m still trying to stick to my deadline of releasing ~something~ by the end of August (even if just a demo or single level), so I have to worry about feature creep. Right now, the character moves in 16×16 grid movement (and it’s action based, but like Arkista’s Ring). If I have time, I’ll refine the game logic for 1×1 pixel movement. Steps like these take longer in the long run, but helps against feature creep in the short run. Having a moveable character, enemies, and a map/area is top priority. If it’s crude, then it’s crude. But crude is better than nothing. Feature creep has pretty much killed a lot of my previous game projects. I’ve used up two days to add this Process queue system, so not too bad. I have an overworld I can walk around in, along with screens (neutopia style), warps (doors/stairs/etc), map collision, and a few other things. Next to work on is player weapon (projectile), life, and enemy collision and AI.

Of course, I have no pixel art or music/sfx. I have to make sure I have time to whip up some crude graphics (rather than the place holders I using now).

If you guys know of any pixel artists that could whip up something quick, send them my way. I thinking something 8bit in design (16×16 segmented look), but with some 16bit color. I.e. keeping it simple. Characters are similar; 16×16 players/enemies 8bit style (Zelda-ish/Arkista’s Ring-ish). I have a music driver that I’m gonna reuse from a demo thingy.

Summer game

Posted in homebrew on August 5, 2014 by pcedev

Been on the ball with going for this little game. The game is top down style (neutopia, falcom, arkista’s ring, etc). I really like that mini char style that Falcom did with it’s early games, and I’m glad they kept it like that on the Popful Mail remake for the PCE. Anyway, I’ve done scrolling engines before (along with collision), but man – this force scroll in section business threw me for a loop. I’d thought it’d be easier, but it’s taken me 5 days to get this thing working (large meta-map/world, force scrolling to next map, etc).

I’m using lots and lots of macros. Mostly to keep the source code as condensed as possible. It looks more like a 16bit processor code than anything else. Really makes thing nice and readable. Almost no performance hit either. When I coded on the 68k, I rarely ever used indexing for direct and indirect addressing, because index wasn’t free and had the over head to setup. So I took that to practice on the macro system I made as well. I have LEA macros as well as ADD.move (base+pointer->address reg), MAPBANK, conditional JSR instructions, long branches (both 16bit and 24bit), 16bit add/sub/shift/rotates/compares, etc. It just makes the source code look compact and easier to read when scrolling through it. I basically reserve X and Y real regs for internal macro support. When I need down to the metal performance, I just use regular 6280 code.

Here’s an example:

;screen collision map
LEA.w [A0],$6000,<A1
ADD.w #$02,<A0
;screen collision map bank
MAPBANK.2 [A0],$6000
INC.w <A0

;set vram address
sVDC_REG MAWR, $0000
sVDC_REG VRWR
;setup pointer
MOVE.w <A1,<A0

MOVE.w #$0000,<A1
MOVE.w #$0040,<A2
MOVE.b #$10,<A3.l
MOVE.b #$0b,<A3.h

.loop
VREG_Select MAWR
MOVE.w <A1,vdata_port
VREG_Select VRWR
MOVE.w [A0], vdata_port
MOVE.w.add [A0], vdata_port, #$01

VREG_Select MAWR
MOVE.w <A2,vdata_port
VREG_Select VRWR
MOVE.w.add [A0], vdata_port, #$02
MOVE.w.add [A0], vdata_port, #$03

ADD.w #$02,<A0 ;map
ADD.w #$02,<A1 ;ptr for row one
ADD.w #$02,<A2 ;ptr for row two

dec <A3.l
beq .check
jmp .loop
.check
MOVE.b #$10,<A3.l
ADD.w #$60,<A1
ADD.w #$60,<A2
dec <A3.h
beq .out
jmp .loop
.out