ANESE/roms/tests/ppu/ppu_read_buffer/source/filler/part1.asm
2017-10-21 17:33:02 -07:00

674 lines
12 KiB
NASM
Executable file
Vendored

bits 16
org 0x110+0x4000+0x2000*3
ROM EQU 0x110 ; ROM begins from this address. No exceptions.
;cpu 386
cpu pentium ; For rdtsc
GenerateNTSCtables EQU 0x6CF0+2 ; This is stored in VROM of the TEST ROM
main:
mov si, xbegins
call GenerateNTSCtables ; Run this routine before possibly loading another ROM
push cs
pop es
push cs
pop ds
mov si, 80h
cld
lodsb
movzx cx, al
inc cx
.NextByte:
dec cx
jz .DoneCommandLine
lodsb
mov ah, 90h ; NOP
cmp al, 'A'
jb .NotUpper
cmp al, 'Z'
ja .NotUpper
or al, 32 ; tolower
.NotUpper:
cmp al, ' '
jbe .NextByte
cmp al, '/'
je .NextByte
cmp al, '-'
je .NextByte
;cmp al, '?'
;je .EnableHelp
;cmp al, 'h'
;je .EnableHelp
cmp al, 'd'
je .EnableDisasm
cmp al, 'g'
je .DisableGraphics
cmp al, 't'
je .DisableGraphics
cmp al, 'n'
je .DisableNTSCsimulation
cmp al, 'p'
je .DisableNTSCsimulation
cmp al, 'm'
je .DisableVESA
cmp al, ':'
je .LoadROM
;jmp .EnableHelp
.EnableHelp:
mov byte [PrintHelp], ah ; NOP
jmp .DoneCommandLine
.EnableDisasm:
mov byte [DEBUG], ah ; NOP
jmp .NextByte
.DisableGraphics:
mov al, 0xC3 ; RET
mov [InitGraphics], al ; Disable graphics mode
mov [ShowScanline], al ; Disable graphics rendering
jmp .NextByte
.DisableNTSCsimulation:
mov al, ah ; mov ax, 0x9090
mov word [NTSC_PALETTE_DISABLE], ax ; nop, so it will do predefined palette
mov word [NTSC_SYNTHESIS_DISABLE], ax ; nop, so it won't jump to NTSC encoder
mov word [NTSC_DECODE_DISABLE], ax ; nop, so it won't jump to NTSC decoder
; Change NTSCdecodeMakeLinear so it won't do un-gammacorrection
mov word [NTSC_DECODE_POWER2], ax
;
mov byte [SCREEN_MARGIN], 8
mov word [RENDER_WIDTH], 256
jmp .NextByte
.DisableVESA:
mov byte [VESA_mode+1], ah
jmp .NextByte
.LoadROM:
; Super secret function: Load another ROM!
; Makes testing so much easier...
; And we still fit in 6000 bytes (compressed).
mov dx, si
rep lodsb
cmp al, 13
jne .NotCR
dec si
.NotCR:
mov ax, 0x3D00
mov [si], al ; Place a nul terminator
int 21h
jc .FileError
xchg bx, ax ; file handle
mov ah, 3Fh
mov cx, main-0x100 ; read everything that we can fit
mov dx, 0x100
int 21h
jc .FileError
mov ah, 3Eh
int 21h
jmp .DoneCommandLine
.FileError:
mov dx, ErrorMsg
mov ah, 9
int 21h
jmp HelpTerminate
.DoneCommandLine:
call PrintHelp
mov byte [C_RESET], 1
; Setup ROM mappings:
mov al, [0x104] ; 16k ROM count
cmp al, 2
ja .FileError ; too large
shl ax, 14 ; multiply by 16384
; Assume we have VRAM...
mov dx, VRAM
; Set a pointer to VROM (it's after the ROM)
cmp byte [0x105], 0 ; 8k VROM count
jz .OnlyVRAM
; Oh, we have VROM instead.
lea dx, [0x110 + eax]
.OnlyVRAM:
mov [VROM], dx
mov [C_VROMPAGE], dx
; Set a pointer to the last ROM page
add ax, ROM - 16384
mov [C_ROMPAGES+2], ax
mov bx, CIRAM+0x0000
mov cx, CIRAM+0x0400
mov al, [0x106]; ctrlbyte
test al, 1
jz .MirrorHorizontal
.MirrorVertical:
xchg bx, cx
.MirrorHorizontal:
mov [C_NTA+2], bx
mov [C_NTA+4], cx
call WaitSpeed
call InitGraphics
call APU_init
call JOY_init
opcode_loop:
call ExecuteOpcode
EscHitFlag:
jmp short opcode_loop
xor dx, dx
jmp ExitEmulation
PrintHelp:
ret ; Patched with NOP where necessary
mov si, [GenerateNTSCtables-2] ; pointer to HelpString is here
cld
.HelpTextLoop:
; Now this help text, because it will be stored in plain
; text without any compression whatsoever, is deliberately
; hidden by simply toggling the high bit of each byte.
lodsb
and al, 7Fh
jz HelpTerminate
xchg dx, ax
call ConsolePutc
jmp short .HelpTextLoop
HelpTerminate:
mov ax, 4C00h
int 21h
WaitSpeed:
call _CPUinfo
fmul dword [const1em3]
fistp dword [.khzspeed]
mov eax, dword 0
.khzspeed EQU $-4
cmp eax, 200000
jae .speed_is_ok
mov cx, 8
std
mov di, CPUspeedText+7
.digitloop:
test eax, eax
jz .zeroloop
mov ebx, 10
xor edx, edx
div ebx
push eax
lea ax, ['0' + edx]
stosb
pop eax
loop .digitloop
jmp .past_zeroloop
.zeroloop:
mov al, ' '
stosb
loop .zeroloop
.past_zeroloop:
mov dx, SlowCPUwarning
mov ah, 9
int 21h
mov ah, 1
int 21h
cmp al, 3
je HelpTerminate
.speed_is_ok:
ret
db 'Joel Yliluoma'
section .const
; This text cannot go to VROM, because it can be accessed
; after a different ROM might have been loaded.
SlowCPUwarning:
db 'Warning: Your CPU is slower than 200 MHz: about'
CPUspeedText:
db ' kHz in fact.',13,10
db 'Suggest running this program in a faster computer.',13,10
db 'If you are using DOSBox, hit Ctrl-F12 to increase the number',13,10
db 'of cycles until the limit is >200k. Even more is better.',13,10
db 'Press a key to continue. Ctrl-C to terminate.',13,10,'$'
ErrorMsg:
db 'ERROR ',13,10,'$'
const1em3 dd 1e-3
section .text
puhh:
; This dummy string is here to thwart people who
; hexdump the ROM. They do not suspect this is actual
; 8086 assembler code. The '$' however is a clue.
;
;db 'Test failed!',13,10,'$'
;
; Ok, on second thought, it's maybe too obscure.
; Let's go the other way: Perplex with a seemingly
; completely irrelevant string. It's a clue.
;
;db $1A,'Incorrect MS-DOS version',13,10
;
; ^ Moved into decompressor stub
;
section .data
C_ROMPAGES dw ROM, ROM
C_NTA: dw CIRAM+0x0000, CIRAM+0x0400, CIRAM+0x0000, CIRAM+0x0400
section .text
;;;;;;; MEMORY READING ;;;;;;;;
RB: ; In: AX = address
; Out: AL = byte
call tick
cmp ax, 0x2000
jae .NotRAM
push bx
and ax, 0x7FF
mov bx, ax
mov al, [RAM+bx]
pop bx
.RB_done:
mov [C_OPENBUS], al
ret
.NotRAM:
cmp ax, 0x4000
jae .NotPPUread
and ax, 7
call PPU_read
jmp short .RB_done
.NotPPUread:
cmp ax, 0x4015
jb .ReadOpenBUS
je APU_read
cmp ax, 0x4017
ja .maybeROMread
call JOY_read
jmp short .RB_done
.maybeROMread:
cmp ax, 0x8000
jb .ReadOpenBUS
push bx
mov bx, [C_ROMPAGES+0]
cmp ax, 0xC000
jb .lowpage
mov bx, [C_ROMPAGES+2]
.lowpage:
and ax, 0x3FFF
add bx, ax
mov al, [bx]
pop bx
jmp short .RB_done
.ReadOpenBUS:
mov al, byte 0x00
C_OPENBUS equ $-1
ret
;;;;;;; MEMORY WRITING ;;;;;;;;
WB: ; In: AX = address
; In: DL = byte
cmp byte [C_RESET], 0
jnz RB
call tick
mov [C_OPENBUS], dl
cmp ax, 0x2000
jae .NotRAM
push bx
and ax, 0x7FF
mov bx, ax
mov byte [RAM+bx], dl
pop bx
ret
.NotRAM:
cmp ax, 0x4000
jae .NotPPUwrite
and ax, 7
jmp PPU_write
.NotPPUwrite:
cmp ax, 0x8000
jae .MapperWrite
cmp ax, 0x6000
jae .PRAM_write
cmp ax, 0x4014
jb APU_write ; 4000..4013
je DMA_write ; 4014
cmp ax, 0x4016
je JOY_write ; 4016
jb APU_write ; 4015
ret
.MapperWrite:
; for now, assume we've got mapper 3 (CNROM)
movzx ax, dl
and al, 3
shl ax, 13 ; mul by 0x2000
add ax, word 0xAAAA
VROM EQU $-2
mov [C_VROMPAGE], ax
ret
.PRAM_write:
cmp ax, 0x6004
jae ConsolePutc
cmp ax, 0x6000
je .MaybeExitCode
.NoWrite:
ret
.MaybeExitCode:
test dl, 0x80
jne .NoWrite
ExitEmulation:
mov al, dl
mov ah, 4Ch
push ax
call Terminate
pop ax
int 21h
ConsolePutc:
or dl, dl
jz .DontOutputNul
push ax
; Output ASCII character to STDOUT
mov ah, 2
int 21h ; dl = character
pop ax
.DontOutputNul:
ret
;;;;;;; CPU ;;;;;;;;;;;;;;
section .data
C_RESET db 0
C_NMI db 0
C_NMI_EDGE db 0
C_IRQ db 0
section .text
%include "exec.inc"
tick:
pusha
call PPU_tick
call PPU_tick
call PPU_tick
call APU_tick
popa
ret
DMA_write:
push dx
mov al, 0
mov ah, dl
.DMA_loop:
push ax
call RB
mov dl, al
mov ax, 0x2004
call WB
pop ax
inc al
jnz .DMA_loop
pop dx
;jmp tick ; one extra tick?
ret
%include "ppu.inc"
%include "apu.inc"
%include "joypad.inc"
section .const
IOsequence:
dw 0x3C4
dw 0x0604 ;chain 4 mode off
dw 0x0100 ;async reset
dw 0,0x3C2
dw 0xE3E3 ;clock suitable for 320x240
dw 0,0x3C4
dw 0x0300 ;restart sequence
dw 0,0x3D4
dw 0x2C11 ;mask out write-protect
dw 0x0D06
dw 0x3E07
dw 0xEA10
dw 0xAC11
dw 0xDF12
dw 0xE715
dw 0x0616
dw 0x0014 ;dword mode off
dw 0xE317 ;byte mode on
dw 0x2813 ;width:320
dw 0,0x3C4
dw 0x0F02
IOsequenceEnd:
section .text
InitModeX:
mov ax, 13h
int 10h
mov si, IOsequence
cld
.NewPort:
lodsw
xchg dx, ax
.IOloop:
cmp si, IOsequenceEnd
je .IOloopEnd
lodsw
test ax,ax
jz .NewPort
out dx, ax
jmp .IOloop
.IOloopEnd:
ret
InitGraphics:
nop
NTSC_PALETTE_DISABLE:
jmp short InitNTSCmode
call InitModeX
; NOT NTSC.
; Because our ROM (the .com file) is not large enough
; to store the actual palette data, even compressed,
; we will instead synthesize it at runtime.
; How? By running the NTSC modem once for each color.
mov al, 16
call PoutBegin
xor ax, ax
.PaletteLoop:
; Generate >=12 samples of NTSC signal
push ax
xor bx, bx
call NTSC_synthesize_with_offset
pop ax
push ax
call NTSC_synthesize_with_offset
; Decode the signal
lea bp, [sincos + 4*4]
mov bx, NTSCline
lea dx, [bx + 12*4]
call NTSCdecodeIntoYUV
call NTSCdecodeMakeR
call Pcalc2
call NTSCdecodeMakeG
call Pcalc2
call NTSCdecodeMakeB
call Pcalc2
pop ax
inc ax
cmp al, 64
jb .PaletteLoop
ret
InitNTSCmode:
; Attempt setting 32-bit 320x240 mode.
; If that doesn't work, fall back to Mode-X, palette & dithering.
mov di, VESA_Info
.NextMode:
mov ax, 0x4F01
inc word [VESA_mode]
mov cx, [VESA_mode]
cmp cx, 0x41FF
jae .No32bitMode
int 0x10
cmp ah, 0
jnz .NextMode
cmp dword [di+0x12], 320 + (240<<16)
jne .NextMode
cmp byte [di+0x19], 32
jne .NextMode
xor eax, eax
mov ax, [di+4]
;mov [VESA_Granularity_kB], ax
shl eax, 10
mov [VESA_Granularity_bytes], eax
mov ax, 0x4F02
mov bx, 0x4013
VESA_mode EQU $-2
int 0x10
cmp ah, 0
jnz .No32bitMode
mov ax, 0x9090
; Change NTSCdecodeMakeLinear so it won't do un-gammacorrection
mov word [NTSC_DECODE_POWER2], ax
mov word [MODEX_RENDERING_ENABLE], ax
mov word [MODEX_DECODE_ENABLE], ax
mov word [MODEX_DECODE_ENABLE+2], ax
ret
.No32bitMode:
call InitModeX
; Set 4*7*9 regular LINEAR palette (252 colors)
; So that dithering will do proper gamma correction.
mov al, 4
call PoutBegin
xor bp, bp
xor si, si
xor di, di
; R = 63*sqrt(r/4)
; G = 63*sqrt(r/7)
; B = 63*sqrt(r/9)
.Ploop:
mov ax, bp
call Pcalc
dd 4.0
mov ax, si
call Pcalc
dd 7.0
mov ax, di
call Pcalc
dd 9.0
inc di
cmp di, 9
jb .Ploop
xor di, di
inc si
cmp si, 7
jb .Ploop
xor si, si
inc bp
cmp bp, 4
jb .Ploop
ret
PoutBegin:
mov dl, 0xC8 ; 3C8
out dx, al
ret
Pcalc:
pop bx
; ax = 63*sqrt(ax / [bx])
mov [.temp], ax
fild word[.temp]
fdiv dword[bx]
fsqrt
fmul dword [const63]
fistp word [.temp]
add bx, 4
push bx
fwait
mov ax, 0
.temp EQU $-2
;jmp PalOutput
PalOutput:
mov dx, 0x3C9
out dx, al
ret
Pcalc2:
call FloatToPositiveIntWithClamp
const63:
dd 63.49
dw 63
jmp short PalOutput
Terminate:
call APU_cleanup
call JOY_cleanup
; Wait for an input key
xor ax, ax
WaitKeyLocation:
int 16h
mov ax, 3
int 10h
ret
;%include "maketestsl.inc"
section .bss
RAM: resb 0x800
OAM: resb 0x100
PALETTE: resb 32
CIRAM: resb 0x400*2
OAM2_x: resb 8
OAM2_index: resb 8
OAM2_attr: resb 8
OAM2_y: resb 8
OAM2_sprindex: resb 8
OAM3_x: resb 8
OAM3_attr: resb 8
OAM3_sprindex: resb 8
OAM3_pattern: resw 8 ; words
xbegins: resd 320 ; Table of NTSCline offsets for each X coordinate
sincos: resd 24 ; sin(pi/6 * x)
NTSCline: resd 8*282
C_VROMPAGE resw 1
VESA_Info EQU NTSCline ; Buffer for holding VESA mode information
; BSS size so far: 0x3A12 bytes.
; With code size around 0x1F3C bytes.
; With org at: 0xA110 (PSP 0x100, HDR 0x10, PRG 0x4000, CHR 3*0x2000)
; This puts the cap at: 0xFA5E.
; Therefore there is no room for VRAM.
VRAM: ;resb 0x2000
; Nor for WRAM, either.