Famicom Disk System Development

Started by aguerrero810, September 24, 2015, 07:36:29 pm

Previous topic - Next topic

80sFREAK

1. BIOS subroutine do.
2. Same as above with more flexibility.

You should check your code AND setting interrupt handlers.

Usually loading subroutines do
a) loading data from start address to end address. return.
b) loading data from start address, specified amount of bytes(words). return.
c) a or b AND jump to the start address(or first adress, where data was loaded).
d) a or b AND jump to the specified address.

We have three handlers

RESET - set to beginnig of your code to avoid go back to FDS menu
IRQ
NMI

or now i miss something  :(
I don't buy, sell or trade at moment.
But my question is how hackers at that time were able to hack those games?(c)krzy

P

1. Not sure how to load a subroutine when my code never loads.
2. Same as above.

The BIOS loads all files that have an ID that is the same or lower as the Boot Read File Code value.
I have three files:
"KYODAKU-" ID: 0
"MAINGAME" ID: 1
"CHRDATA1" ID: 2

And my Boot Read File Code is set to $0F so all these files should load at boot automatically. The KYODAKU- file successfully loads since the message comes scrolling up. And the CHRDATA1 file also loads according to the PPU debugger in my emulator. But the MAINGAME file never loads, or at least it never executes.

I tried moving up the RESET handler to the beginning of the file but it doesn't change anything.

aguerrero810

Same. I also noticed that on the FDS page on NesDev. It says you should write $C0 to $0101 to use your own IRQ routine.

Quote from: NesDev Wiki
A few important notes :
After loading the boot files, $102 is set to $35 so that the ($DFFC) vector is used and the BIOS is skipped.
$103 indicate reset type : $AC = first boot of the game, $53 = the game was soft-reseted by the user
To use your own IRQ routine, you must manually write $c0 to $101
There is 3 possible NMI vectors, #3 is used by default.
On first start, the mirroring is set to horizontal, the stack pointer is $ff, and the I flag is clear. System RAM is filled with values used by the BIOS, and PRG RAM is uninitialized, except for parts of it which has files loaded in.


But in your FDS_HOOK code you are writing $80. Although you aren't doing much in IRQ except for jumping to FDS_HOOK. I changed it to $C0 but nothing different happened.

P

You only need to write $C0 if you are using IRQ, which I'm not (I just put an FDS_HOOK jsr there for the sake of it). After boot-up, $0101 is set to $80 by the BIOS (so IRQs are turned off by default).

aguerrero810

October 04, 2015, 11:04:30 am #19 Last Edit: October 04, 2015, 01:13:53 pm by aguerrero810
I also found in Brad Taylor's Technical Reference:
Quote
Booting a disk game
-------------------
Once a disk's boot files have been loaded successfully into memory (more on
this later), ($0102) is assigned $AC35, and the BIOS data area (and their
respective ports) are set to the aforementioned reset values. Finally,
interrupts are enabled, and program control is transfered to the ($DFFC)
vector.


Program control is transferred to the $DFFC vector. Which is exactly right. It should be loading my code:

main:
  ldx #$00
  inx
  jmp main

I looked at the hex and everything.  :- This is puzzling.

Post Merge: October 04, 2015, 01:13:53 pm

Using the Hex Editor in FCEUX i can confirm that the code in MAINGAME is not even loading into PRAM. Very Puzzling.

P

I double checked the header file again and I can't find anything wrong with it. I bet the problem is in the MAINGAME file, or there's something there we don't understand properly.

80sFREAK

/sarcasm mode on/ Sorry, can't help you much, my mind occupied by greediness of making bootleg repros /sarcasm mode off/

The best you can do is disassemble BIOS to figure out, how exactly it is working. Or check Enri's page, maybe info already there.
I don't buy, sell or trade at moment.
But my question is how hackers at that time were able to hack those games?(c)krzy

P

There are documents out there with parts of the BIOS disassembled I think. It's just that they get a bit too technical for a simple layman like me. I need a working example, and tried making it myself since there is none AFAIK.

Chris Covell is one of few people that has already successfully made some FDS homebrew but I can't make head or tail out of his source code.

aguerrero810

October 05, 2015, 06:02:51 pm #23 Last Edit: October 05, 2015, 06:16:16 pm by aguerrero810
So i got it to work after emailing Chris, and the solution is kinda silly.
When you make the files in the FDS image, the vectors themselves don't go in to the disk at $DFF6. They are going to be loaded into PRAM which is at $6000. This means you must position your vectors on the disk so that when they are loaded, they land at $DFF6. This can be tricky and I had to hand code most of the label-work to get it to boot my code.

EDIT:
And another reason it wasn't loading was that the file was too big. When you
.org DFF6
then you are making that file really big. Too big actually. For my test, I set the MAINGAME file to go into PRAM at $DFE0 so that loading would be quick. Then It was a matter of setting the vectors to go in the right places. I still need to figure out a way for the assembler to find the values for my JMPs and vectors, so I don't have to manually type them in.

P

I see, that explains why I ran out of disk space when I tried to add more data although I only had three quite small files.

aguerrero810

Brad Taylor has released his Development Kit that he uses for FDS Development. It's pretty cool and makes writing programs a lot simpler. His assembler format is a little weird.
Stuff like
LDA #$00
turns into
lda_ imd,00h
but if you can tolerate that, it's pretty nice.

Another tip on fast game loading, if you put the Reset, NMI, and IRQ vectors in a seperate File on the FDS image, and have it load at $DFF6, it is a lot faster than loading a bunch of 0's from $6000 to $DFF6 until you hit the vectors in your program.

Also, skipping the KYODAKU- is something Brad Taylor has talked about before. All you need is a one-byte file that loads into $2000 and contains $80. This sets the NMI to fire on vblanks. Then you load a file that is at least $100 large that loads into a useless space in PRAM. This way, the BIOS doesn't have time to complain on missing the KYODAKU- file. Do this after loading your MAINGAME file. In the MAINGAME file, you then need to reinstall the vector for some reason.

Here's something I made using Brad Taylor's assembler:

model small
codeseg
org 0

include ..\fds.inc
include ..\6502.inc

start: ret

;----------------------------------------------------------------------------
; DECLARE TILE SET

FDSchr 'MARIOCHR',0000h,endchr
db 8192 dup(?)
endchr:

;----------------------------------------------------------------------------
; Constants

        SPEED = 5


;----------------------------------------------------------------------------
; RESET & INIT

FDSprg ' EXAMPLE',6000h,endprg

;disable video(bg+obj), VINT, disk system
reset:
        sei_
        cld_
lda_ imd,27h
        sta_ abz,4025h;        shut down disk system
ldx_ imd,-1
        txs_

;install NMI handler (required, due to avoiding the KYODAKU copyright screen)
lda_ imd,<(nmi-start)and 255>
        sta_ abz,0dffah
lda_ imd,<(nmi-start)shr 8>
        sta_ abz,0dffbh

;clear memory
        ldx_ imd,0
clrmem:
        lda_ imd,0
        sta_ abx,0000h
        sta_ abx,0300h
        sta_ abx,0400h
        sta_ abx,0500h
        sta_ abx,0600h
        sta_ abx,0700h
        lda_ imd,11111110b
        sta_ abx,0200h;        clear all the sprites
        inx_
        bne_ clrmem
                           
;load palette
        lda_ abz,2002h;        reset the write high/low latch
        lda_ imd,3fh
        sta_ abz,2006h
        lda_ imd,00h
        sta_ abz,2006h;        set the ppu address to $3f00
        tax_
paletteloop:
        lda_ abx,colpal
        sta_ abz,2007h
        inx_
        cpx_ imd,20h
        bne_ paletteloop

;load sprites from DBs
        ldx_ imd,0
spriteloop:
        lda_ abx,sprites
        sta_ abx,0200h
        inx_
        cpx_ imd,10h
        bne_ spriteloop

;turn on screen
        lda_ imd,10000000b
        sta_ abz,2000h;        enable NMI
        lda_ imd,00010000b
        sta_ abz,2001h;        enable sprites

lp:     jmp_ abz,lp;           infinite loop

;----------------------------------------------------------------------------
; Color Palette
colpal:
        db 0fh,31h,32h,33h,0fh,35h,36h,37h,0fh,39h,3ah,3bh,0fh,3dh,3eh,0fh;bg
        db 0fh,0fh,10h,30h,0fh,01h,21h,31h,0fh,36h,16h,0fh,0fh,29h,1ah,0fh;fg

;----------------------------------------------------------------------------
; Initial Sprite DBs
sprites:
;        vert,tile,attr,horiz
        db 70h,32h,03h,70h;    sprite 0
        db 70h,33h,03h,78h;    sprite 1
        db 78h,34h,03h,70h;    sprite 2
        db 78h,35h,03h,78h;    sprite 3

;----------------------------------------------------------------------------
; VBLANK

NMI:
;sprite dma from $0200
        lda_ imd,0
        sta_ abz,2003h
        lda_ imd,02h
        sta_ abz,4014h

;controller handling
        lda_ imd,01h
        sta_ abz,4016h
        lda_ imd,00h
        sta_ abz,4016h;        strobe buttons to latch positions

        lda_ abz,4016h;        Player 1 - A
        and_ imd,00000001b
        bne_ read1adone
        lda_ zpg,00h
        clc_
        adc_ imd,01h
        sta_ zpg,00h
read1adone: 

        lda_ abz,4016h;        Player 1 - B
        and_ imd,00000001b
        bne_ read1bdone
        lda_ zpg,00h
        sec_
        sbc_ imd,01h
        sta_ zpg,00h
read1bdone: 

        lda_ abz,4016h;        Player 1 - Select
read1seldone:

        lda_ abz,4016h;        Player 1 - Start
read1stadone:

        lda_ abz,4016h;        Player 1 - Up
        and_ imd,00000001b
        beq_ read1updone
        x=0
        rept 4
         lda_ abz,0200h+x
         sec_
         sbc_ zpg,00h
         sta_ abz,0200h+x;
         x=x+4
        endm
read1updone:

        lda_ abz,4016h;        Player 1 - Down
        and_ imd,00000001b
        beq_ read1dwndone
        x=0
        rept 4
         lda_ abz,0200h+x
         clc_
         adc_ zpg,00h
         sta_ abz,0200h+x;
         x=x+4
        endm
read1dwndone:

        lda_ abz,4016h;        Player 1 - Left
        and_ imd,00000001b
        beq_ read1lftdone
        x=0
        rept 4
         lda_ abz,0203h+x
         sec_
         sbc_ zpg,00h
         sta_ abz,0203h+x
         x=x+4
        endm
read1lftdone:

        lda_ abz,4016h;        Player 1 - Right
        and_ imd,00000001b
        beq_ read1rgtdone
        x=0
        rept 4
         lda_ abz,0203h+x
         clc_
         adc_ zpg,00h
         sta_ abz,0203h+x;
         x=x+4
        endm
read1rgtdone:

        rti_
;----------------------------------------------------------------------------
endprg:
        FDSend  reset,reset;   irq
ends
end start


All it does is put mario on the screen, and let you move him around with different speeds.

Hope this Helps!

P


famifan

Quote from: P on September 25, 2015, 12:00:45 pm

main:
  ;main program loop here
  jmp main




man, it looks like an endless loop. Main goes to main again and again. Was it intentional?

have you tried to put some more code into 'main' loop?

chowder

Quote from: famifan on October 26, 2015, 07:28:01 am
Quote from: P on September 25, 2015, 12:00:45 pm

main:
  ;main program loop here
  jmp main




man, it looks like an endless loop. Main goes to main again and again. Was it intentional?

have you tried to put some more code into 'main' loop?


It's probably supposed to be like that, with NMIs set to fire on VBlank the NMI functions will run in parallel to that loop.

famifan